If the malloc of our struct nvme_mi_transport_mctp fails, we'll attempt
to free ->rsp_buf of this (now zero) pointer.
Instead, structure the error path to progressively undo the
initialisation operations. This means we'll need to save the errno at
the site of each possible failure.
In doing this, add a comment to the call to nvme_mi_close(), just to
clarify behaviour with regards to the cleanups through that path.
Reported-by: Barnabás Pőcze <pobrn@protonmail.com>
Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
return NULL;
mctp = malloc(sizeof(*mctp));
- if (!mctp)
- goto err_free_ep;
+ if (!mctp) {
+ errno_save = errno;
+ goto err_close_ep;
+ }
memset(mctp, 0, sizeof(*mctp));
mctp->sd = -1;
mctp->resp_buf_size = 4096;
mctp->resp_buf = malloc(mctp->resp_buf_size);
- if (!mctp->resp_buf)
- goto err_free_ep;
+ if (!mctp->resp_buf) {
+ errno_save = errno;
+ goto err_free_mctp;
+ }
mctp->net = netid;
mctp->eid = eid;
mctp->sd = ops.socket(AF_MCTP, SOCK_DGRAM, 0);
- if (mctp->sd < 0)
- goto err_free_ep;
+ if (mctp->sd < 0) {
+ errno_save = errno;
+ goto err_free_rspbuf;
+ }
ep->transport = &nvme_mi_transport_mctp;
ep->transport_data = mctp;
return ep;
-err_free_ep:
- errno_save = errno;
- nvme_mi_close(ep);
+err_free_rspbuf:
free(mctp->resp_buf);
+err_free_mctp:
free(mctp);
+err_close_ep:
+ /* the ep->transport is not set yet, so this will not call back
+ * into nvme_mi_mctp_close() */
+ nvme_mi_close(ep);
errno = errno_save;
return NULL;
}