Merge branch 'js/coverity-fixes'

Various resource leaks, invalid file descriptor closures, and process
handle ownership issues flagged by Coverity have been fixed.

* js/coverity-fixes:
  mingw: make `exit_process()` own the process handle on all paths
  fsmonitor: plug token-data leak on early daemon-startup failures
  reftable/table: release filter on error path
  imap-send: avoid leaking the IMAP upload buffer
  worktree: fix resource leaks when branch creation fails
  submodule: fix cwd leak in `get_superproject_working_tree()`
  dir: free allocations on parse-error paths in `read_one_dir()`
  line-log: avoid redundant copy that leaks in process_ranges
  run-command: avoid `close(-1)` in `start_command()` error paths
  download_https_uri_to_file(): do not leak fd upon failure
  loose: avoid closing invalid fd on error path
  load_one_loose_object_map(): fix resource leak
main
Junio C Hamano 2026-07-16 23:05:47 -07:00
commit 347fe8a91b
11 changed files with 41 additions and 26 deletions

View File

@ -1418,6 +1418,8 @@ static int fsmonitor_run_daemon(void)
err = fsmonitor_run_daemon_1(&state);

done:
fsmonitor_free_token_data(state.current_token_data);
state.current_token_data = NULL;
pthread_cond_destroy(&state.cookies_cond);
pthread_mutex_destroy(&state.main_lock);
{

View File

@ -945,14 +945,17 @@ static int add(int ac, const char **av, const char *prefix,
strvec_push(&cp.args, branch);
if (opt_track)
strvec_push(&cp.args, opt_track);
if (run_command(&cp))
return -1;
if (run_command(&cp)) {
ret = -1;
goto cleanup;
}
branch = new_branch;
} else if (opt_track) {
die(_("--[no-]track can only be used if a new branch is created"));
}

ret = add_worktree(path, branch, &opts);
cleanup:
free(path);
free(opt_track);
free(branch_to_free);

View File

@ -378,7 +378,7 @@ cleanup:
if (child_in)
fclose(child_in);
if (finish_command(&cp))
return 1;
result = 1;
if (child_out)
fclose(child_out);
return result;

View File

@ -2269,10 +2269,8 @@ int mingw_kill(pid_t pid, int sig)
}
ret = terminate_process_tree(h, 128 + sig);
}
if (ret) {
if (ret)
errno = err_win_to_posix(GetLastError());
CloseHandle(h);
}
return ret;
} else if (pid > 0 && sig == 0) {
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);

View File

@ -159,6 +159,7 @@ static int exit_process(HANDLE process, int exit_code)
return terminate_process_tree(process, exit_code);
}

CloseHandle(process);
return 0;
}


9
dir.c
View File

@ -3792,13 +3792,18 @@ static int read_one_dir(struct untracked_cache_dir **untracked_,
ALLOC_ARRAY(ud.untracked, ud.untracked_nr);

ud.dirs_alloc = ud.dirs_nr = decode_varint(&data);
if (data > end)
if (data > end) {
free(ud.untracked);
return -1;
}
ALLOC_ARRAY(ud.dirs, ud.dirs_nr);

eos = memchr(data, '\0', end - data);
if (!eos || eos == end)
if (!eos || eos == end) {
free(ud.untracked);
free(ud.dirs);
return -1;
}

*untracked_ = untracked = xmalloc(st_add3(sizeof(*untracked), eos - data, 1));
memcpy(untracked, &ud, sizeof(ud));

View File

@ -1750,6 +1750,7 @@ static int curl_append_msgs_to_imap(struct imap_server_conf *server,

curl_easy_cleanup(curl);
curl_global_cleanup();
strbuf_release(&msgbuf.buf);

if (cred.username) {
if (res == CURLE_OK)

12
loose.c
View File

@ -65,6 +65,7 @@ static int load_one_loose_object_map(struct repository *repo, struct odb_source_
{
struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
FILE *fp;
int ret = -1;

if (!loose->map)
loose_object_map_init(&loose->map);
@ -84,7 +85,6 @@ static int load_one_loose_object_map(struct repository *repo, struct odb_source_
return 0;
}

errno = 0;
if (strbuf_getwholeline(&buf, fp, '\n') || strcmp(buf.buf, loose_object_header))
goto err;
while (!strbuf_getline_lf(&buf, fp)) {
@ -98,13 +98,12 @@ static int load_one_loose_object_map(struct repository *repo, struct odb_source_
insert_loose_map(loose, &oid, &compat_oid);
}

strbuf_release(&buf);
strbuf_release(&path);
return errno ? -1 : 0;
ret = ferror(fp) ? -1 : 0;
err:
fclose(fp);
strbuf_release(&buf);
strbuf_release(&path);
return -1;
return ret;
}

int repo_read_loose_object_map(struct repository *repo)
@ -202,7 +201,8 @@ static int write_one_object(struct odb_source_loose *loose,
return 0;
errout:
error_errno(_("failed to write loose object index %s"), path.buf);
close(fd);
if (fd >= 0)
close(fd);
rollback_lock_file(&lock);
strbuf_release(&buf);
strbuf_release(&path);

View File

@ -709,6 +709,10 @@ out:
if (ti)
table_iter_close(ti);
reftable_free(ti);
if (filter) {
reftable_buf_release(&filter->oid);
reftable_free(filter);
}
}
return err;
}

View File

@ -706,7 +706,7 @@ int start_command(struct child_process *cmd)
failed_errno = errno;
if (need_in)
close_pair(fdin);
else if (cmd->in)
else if (cmd->in > 0)
close(cmd->in);
str = "standard output";
goto fail_pipe;
@ -720,11 +720,11 @@ int start_command(struct child_process *cmd)
failed_errno = errno;
if (need_in)
close_pair(fdin);
else if (cmd->in)
else if (cmd->in > 0)
close(cmd->in);
if (need_out)
close_pair(fdout);
else if (cmd->out)
else if (cmd->out > 0)
close(cmd->out);
str = "standard error";
fail_pipe:

View File

@ -2627,13 +2627,12 @@ int get_superproject_working_tree(struct strbuf *buf)
* We might have a superproject, but it is harder
* to determine.
*/
return 0;
goto out;

if (!strbuf_realpath(&one_up, "../", 0))
return 0;
goto out;

subpath = relative_path(cwd, one_up.buf, &sb);
strbuf_release(&one_up);

prepare_submodule_repo_env(&cp.env);
strvec_pop(&cp.env);
@ -2678,20 +2677,22 @@ int get_superproject_working_tree(struct strbuf *buf)
ret = 1;
free(super_wt);
}
free(cwd);
strbuf_release(&sb);

code = finish_command(&cp);

if (code == 128)
/* '../' is not a git repository */
return 0;
if (code == 0 && len == 0)
ret = 0;
else if (code == 0 && len == 0)
/* There is an unrelated git repository at '../' */
return 0;
if (code)
ret = 0;
else if (code)
die(_("ls-tree returned unexpected return code %d"), code);

out:
strbuf_release(&sb);
strbuf_release(&one_up);
free(cwd);
return ret;
}