nfs_write_async: plug potential memory leaks
[deb_libnfs.git] / lib / libnfs.c
index eab8fd2d936216408167d6f822604c66f2bc473f..c697895f68c4ab88893ee18111306575b22f34a6 100644 (file)
@@ -1775,6 +1775,10 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs
                return 0;
        }
 
+       /* hello, clang-analyzer */
+       assert(count > 0);
+       assert(data->num_calls == 0);
+
        /* trying to write more than maximum server write size, we has to chop it up into smaller
         * chunks.
         * we send all writes in parallel so that performance is still good.
@@ -1794,6 +1798,8 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs
                mdata = malloc(sizeof(struct nfs_mcb_data));
                if (mdata == NULL) {
                        rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_mcb_data structure");
+                       if (data->num_calls == 0)
+                               free_nfs_cb_data(data);
                        return -1;
                }
                memset(mdata, 0, sizeof(struct nfs_mcb_data));
@@ -1813,6 +1819,9 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs
                        rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path);
                        data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                        free(mdata);
+                       if (data->num_calls == 0)
+                               free_nfs_cb_data(data);
+
                        return -1;
                }
 
@@ -2124,6 +2133,7 @@ int nfs_mkdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *
 
        ptr = strrchr(new_path, '/');
        if (ptr == NULL) {
+               free(new_path);
                rpc_set_error(nfs->rpc, "Invalid path %s", path);
                return -1;
        }
@@ -2210,6 +2220,7 @@ int nfs_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *
 
        ptr = strrchr(new_path, '/');
        if (ptr == NULL) {
+               free(new_path);
                rpc_set_error(nfs->rpc, "Invalid path %s", path);
                return -1;
        }
@@ -2445,6 +2456,7 @@ int nfs_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void
 
        ptr = strrchr(new_path, '/');
        if (ptr == NULL) {
+               free(new_path);
                rpc_set_error(nfs->rpc, "Invalid path %s", path);
                return -1;
        }
@@ -2594,7 +2606,6 @@ int nfs_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev
        /* data->path now points to the parent directory,  and beyond the nul terminateor is the new directory to create */
        if (nfs_lookuppath_async(nfs, cb_data->path, cb, private_data, nfs_mknod_continue_internal, cb_data, free_mknod_cb_data, 0) != 0) {
                rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
-               free_mknod_cb_data(cb_data);
                return -1;
        }
 
@@ -2729,6 +2740,7 @@ static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_d
                nfsdirent->name = strdup(entry->name);
                if (nfsdirent->name == NULL) {
                        data->cb(-ENOMEM, nfs, "Failed to allocate dirent->name", data->private_data);
+                       free(nfsdirent);
                        nfs_free_nfsdir(nfsdir);
                        data->continue_data = NULL;
                        free_nfs_cb_data(data);
@@ -2788,6 +2800,9 @@ static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_d
                         * commands in flight to complete
                         */
                        if (rdpe_cb_data->getattrcount > 0) {
+                               nfs_free_nfsdir(nfsdir);
+                               data->continue_data = NULL;
+                               free_nfs_cb_data(data);
                                rdpe_cb_data->status = RPC_STATUS_ERROR;
                                free(rdpe_lookup_cb_data);
                                return;
@@ -2805,7 +2820,6 @@ static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_d
        }
 }
 
-
 static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
 {
        READDIRPLUS3res *res = command_data;
@@ -3309,7 +3323,6 @@ int nfs_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs
        memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len);
 
        if (nfs_chmod_continue_internal(nfs, data) != 0) {
-               free_nfs_cb_data(data);
                return -1;
        }
 
@@ -3444,7 +3457,6 @@ int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int
        memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len);
 
        if (nfs_chown_continue_internal(nfs, data) != 0) {
-               free_nfs_cb_data(data);
                return -1;
        }
 
@@ -3886,19 +3898,28 @@ static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb
 static int nfs_rename_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
 {
        struct nfs_rename_data *rename_data = data->continue_data;
+       char* newpath = strdup(rename_data->newpath);
+       if (!newpath) {
+               rpc_set_error(nfs->rpc, "Out of memory. Could not allocate memory to store target path for rename");
+               data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
+               free_nfs_cb_data(data);
+               return -1;
+       }
 
        /* steal the filehandle */
        rename_data->olddir = data->fh;
        data->fh.data.data_val = NULL;
 
        if (nfs_lookuppath_async(nfs, rename_data->newpath, data->cb, data->private_data, nfs_rename_continue_2_internal, rename_data, free_nfs_rename_data, 0) != 0) {
-               rpc_set_error(nfs->rpc, "RPC error: Failed to send LOOKUP call for %s", rename_data->newpath);
+               rpc_set_error(nfs->rpc, "RPC error: Failed to send LOOKUP call for %s", newpath);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
+               free(newpath);
                return -1;
        }
        data->continue_data = NULL;
        free_nfs_cb_data(data);
+       free(newpath);
 
        return 0;
 }