git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 25/34] send-pack: release strbuf on error return in send_pack()

From
Rene Scharfe <l.s.r@web.de>
Date
Aug 30, 2017, 18:20 UTC
Message-ID
<20170830182013.21106-1-l.s.r@web.de>
In-Reply-To
<20170830175005.20756-1-l.s.r@web.de>
Signed-off-by: Rene Scharfe <l.s.r@web.de>
---
 send-pack.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/send-pack.c b/send-pack.c
index 11d6f3d983..b865f662e4 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -377,253 +377,256 @@ static void reject_invalid_nonce(const char *nonce, int len)
 int send_pack(struct send_pack_args *args,
 	      int fd[], struct child_process *conn,
 	      struct ref *remote_refs,
 	      struct oid_array *extra_have)
 {
 	int in = fd[0];
 	int out = fd[1];
 	struct strbuf req_buf = STRBUF_INIT;
 	struct strbuf cap_buf = STRBUF_INIT;
 	struct ref *ref;
 	int need_pack_data = 0;
 	int allow_deleting_refs = 0;
 	int status_report = 0;
 	int use_sideband = 0;
 	int quiet_supported = 0;
 	int agent_supported = 0;
 	int use_atomic = 0;
 	int atomic_supported = 0;
 	int use_push_options = 0;
 	int push_options_supported = 0;
 	unsigned cmds_sent = 0;
 	int ret;
 	struct async demux;
 	const char *push_cert_nonce = NULL;
 
 	/* Does the other end support the reporting? */
 	if (server_supports("report-status"))
 		status_report = 1;
 	if (server_supports("delete-refs"))
 		allow_deleting_refs = 1;
 	if (server_supports("ofs-delta"))
 		args->use_ofs_delta = 1;
 	if (server_supports("side-band-64k"))
 		use_sideband = 1;
 	if (server_supports("quiet"))
 		quiet_supported = 1;
 	if (server_supports("agent"))
 		agent_supported = 1;
 	if (server_supports("no-thin"))
 		args->use_thin_pack = 0;
 	if (server_supports("atomic"))
 		atomic_supported = 1;
 	if (server_supports("push-options"))
 		push_options_supported = 1;
 
 	if (args->push_cert != SEND_PACK_PUSH_CERT_NEVER) {
 		int len;
 		push_cert_nonce = server_feature_value("push-cert", &len);
 		if (push_cert_nonce) {
 			reject_invalid_nonce(push_cert_nonce, len);
 			push_cert_nonce = xmemdupz(push_cert_nonce, len);
 		} else if (args->push_cert == SEND_PACK_PUSH_CERT_ALWAYS) {
 			die(_("the receiving end does not support --signed push"));
 		} else if (args->push_cert == SEND_PACK_PUSH_CERT_IF_ASKED) {
 			warning(_("not sending a push certificate since the"
 				  " receiving end does not support --signed"
 				  " push"));
 		}
 	}
 
 	if (!remote_refs) {
 		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
 			"Perhaps you should specify a branch such as 'master'.\n");
 		return 0;
 	}
 	if (args->atomic && !atomic_supported)
 		die(_("the receiving end does not support --atomic push"));
 
 	use_atomic = atomic_supported && args->atomic;
 
 	if (args->push_options && !push_options_supported)
 		die(_("the receiving end does not support push options"));
 
 	use_push_options = push_options_supported && args->push_options;
 
 	if (status_report)
 		strbuf_addstr(&cap_buf, " report-status");
 	if (use_sideband)
 		strbuf_addstr(&cap_buf, " side-band-64k");
 	if (quiet_supported && (args->quiet || !args->progress))
 		strbuf_addstr(&cap_buf, " quiet");
 	if (use_atomic)
 		strbuf_addstr(&cap_buf, " atomic");
 	if (use_push_options)
 		strbuf_addstr(&cap_buf, " push-options");
 	if (agent_supported)
 		strbuf_addf(&cap_buf, " agent=%s", git_user_agent_sanitized());
 
 	/*
 	 * NEEDSWORK: why does delete-refs have to be so specific to
 	 * send-pack machinery that set_ref_status_for_push() cannot
 	 * set this bit for us???
 	 */
 	for (ref = remote_refs; ref; ref = ref->next)
 		if (ref->deletion && !allow_deleting_refs)
 			ref->status = REF_STATUS_REJECT_NODELETE;
 
 	if (!args->dry_run)
 		advertise_shallow_grafts_buf(&req_buf);
 
 	if (!args->dry_run && push_cert_nonce)
 		cmds_sent = generate_push_cert(&req_buf, remote_refs, args,
 					       cap_buf.buf, push_cert_nonce);
 
 	/*
 	 * Clear the status for each ref and see if we need to send
 	 * the pack data.
 	 */
 	for (ref = remote_refs; ref; ref = ref->next) {
 		switch (check_to_send_update(ref, args)) {
 		case 0: /* no error */
 			break;
 		case CHECK_REF_STATUS_REJECTED:
 			/*
 			 * When we know the server would reject a ref update if
 			 * we were to send it and we're trying to send the refs
 			 * atomically, abort the whole operation.
 			 */
-			if (use_atomic)
+			if (use_atomic) {
+				strbuf_release(&req_buf);
+				strbuf_release(&cap_buf);
 				return atomic_push_failure(args, remote_refs, ref);
+			}
 			/* Fallthrough for non atomic case. */
 		default:
 			continue;
 		}
 		if (!ref->deletion)
 			need_pack_data = 1;
 
 		if (args->dry_run || !status_report)
 			ref->status = REF_STATUS_OK;
 		else
 			ref->status = REF_STATUS_EXPECTING_REPORT;
 	}
 
 	/*
 	 * Finally, tell the other end!
 	 */
 	for (ref = remote_refs; ref; ref = ref->next) {
 		char *old_hex, *new_hex;
 
 		if (args->dry_run || push_cert_nonce)
 			continue;
 
 		if (check_to_send_update(ref, args) < 0)
 			continue;
 
 		old_hex = oid_to_hex(&ref->old_oid);
 		new_hex = oid_to_hex(&ref->new_oid);
 		if (!cmds_sent) {
 			packet_buf_write(&req_buf,
 					 "%s %s %s%c%s",
 					 old_hex, new_hex, ref->name, 0,
 					 cap_buf.buf);
 			cmds_sent = 1;
 		} else {
 			packet_buf_write(&req_buf, "%s %s %s",
 					 old_hex, new_hex, ref->name);
 		}
 	}
 
 	if (use_push_options) {
 		struct string_list_item *item;
 
 		packet_buf_flush(&req_buf);
 		for_each_string_list_item(item, args->push_options)
 			packet_buf_write(&req_buf, "%s", item->string);
 	}
 
 	if (args->stateless_rpc) {
 		if (!args->dry_run && (cmds_sent || is_repository_shallow())) {
 			packet_buf_flush(&req_buf);
 			send_sideband(out, -1, req_buf.buf, req_buf.len, LARGE_PACKET_MAX);
 		}
 	} else {
 		write_or_die(out, req_buf.buf, req_buf.len);
 		packet_flush(out);
 	}
 	strbuf_release(&req_buf);
 	strbuf_release(&cap_buf);
 
 	if (use_sideband && cmds_sent) {
 		memset(&demux, 0, sizeof(demux));
 		demux.proc = sideband_demux;
 		demux.data = fd;
 		demux.out = -1;
 		demux.isolate_sigpipe = 1;
 		if (start_async(&demux))
 			die("send-pack: unable to fork off sideband demultiplexer");
 		in = demux.out;
 	}
 
 	if (need_pack_data && cmds_sent) {
 		if (pack_objects(out, remote_refs, extra_have, args) < 0) {
 			for (ref = remote_refs; ref; ref = ref->next)
 				ref->status = REF_STATUS_NONE;
 			if (args->stateless_rpc)
 				close(out);
 			if (git_connection_is_socket(conn))
 				shutdown(fd[0], SHUT_WR);
 
 			/*
 			 * Do not even bother with the return value; we know we
 			 * are failing, and just want the error() side effects.
 			 */
 			if (status_report)
 				receive_unpack_status(in);
 
 			if (use_sideband) {
 				close(demux.out);
 				finish_async(&demux);
 			}
 			fd[1] = -1;
 			return -1;
 		}
 		if (!args->stateless_rpc)
 			/* Closed by pack_objects() via start_command() */
 			fd[1] = -1;
 	}
 	if (args->stateless_rpc && cmds_sent)
 		packet_flush(out);
 
 	if (status_report && cmds_sent)
 		ret = receive_status(in, remote_refs);
 	else
 		ret = 0;
 	if (args->stateless_rpc)
 		packet_flush(out);
 
 	if (use_sideband && cmds_sent) {
 		close(demux.out);
 		if (finish_async(&demux)) {
 			error("error in sideband demultiplexer");
 			ret = -1;
 		}
 	}
 
 	if (ret < 0)
 		return ret;
 
 	if (args->porcelain)
 		return 0;
 
 	for (ref = remote_refs; ref; ref = ref->next) {
 		switch (ref->status) {
 		case REF_STATUS_NONE:
 		case REF_STATUS_UPTODATE:
 		case REF_STATUS_OK:
 			break;
 		default:
 			return -1;
 		}
 	}
 	return 0;
 }
-- 
2.14.1
Previous: Rene ScharfeNext: Rene Scharfe
Message 71 of 75 in “plug strbuf memory leaks”
  1. 00/34 plug strbuf memory leaksRene Scharfe, Aug 30, 2017
  2. 01/34 am: release strbufs after use in detect_patch_format()Rene Scharfe, Aug 30, 2017
  3. Stefan BellerAug 31, 2017
  4. 02/34 am: release strbuf on error return in hg_patch_to_mail()Rene Scharfe, Aug 30, 2017
  5. 05/34 clean: release strbuf after use in remove_dirs()Rene Scharfe, Aug 30, 2017
  6. 06/34 clone: release strbuf after use in remove_junk()Rene Scharfe, Aug 30, 2017
  7. Junio C HamanoSep 6, 2017
  8. René ScharfeSep 10, 2017
  9. Jeff KingSep 10, 2017
  10. René ScharfeSep 10, 2017
  11. Jeff KingSep 10, 2017
  12. René ScharfeSep 11, 2017
  13. Jeff KingSep 13, 2017
  14. 07/34 commit: release strbuf on error return in commit_tree_extended()Rene Scharfe, Aug 30, 2017
  15. Stefan BellerAug 31, 2017
  16. 19/34 merge: release strbuf after use in write_merge_heads()Rene Scharfe, Aug 30, 2017
  17. 10/34 diff: release strbuf after use in diff_summary()Rene Scharfe, Aug 30, 2017
  18. Stefan BellerAug 31, 2017
  19. 14/34 help: release strbuf on error return in exec_man_man()Rene Scharfe, Aug 30, 2017
  20. 15/34 help: release strbuf on error return in exec_woman_emacs()Rene Scharfe, Aug 30, 2017
  21. 18/34 merge: release strbuf after use in save_state()Rene Scharfe, Aug 30, 2017
  22. 16/34 mailinfo: release strbuf after use in handle_from()Rene Scharfe, Aug 30, 2017
  23. 17/34 mailinfo: release strbuf on error return in handle_boundary()Rene Scharfe, Aug 30, 2017
  24. Martin ÅgrenAug 30, 2017
  25. René ScharfeAug 31, 2017
  26. Martin ÅgrenSep 5, 2017
  27. 13/34 help: release strbuf on error return in exec_man_konqueror()Rene Scharfe, Aug 30, 2017
  28. 09/34 convert: release strbuf on error return in filter_buffer_or_fd()Rene Scharfe, Aug 30, 2017
  29. 08/34 connect: release strbuf on error return in git_connect()Rene Scharfe, Aug 30, 2017
  30. Stefan BellerAug 31, 2017
  31. 03/34 am: release strbuf after use in safe_to_abort()Rene Scharfe, Aug 30, 2017
  32. 04/34 check-ref-format: release strbuf after use in check_ref_format_branch()Rene Scharfe, Aug 30, 2017
  33. 11/34 diff: release strbuf after use in show_rename_copy()Rene Scharfe, Aug 30, 2017
  34. 12/34 diff: release strbuf after use in show_stats()Rene Scharfe, Aug 30, 2017
  35. 20/34 notes: release strbuf after use in notes_copy_from_stdin()Rene Scharfe, Aug 30, 2017
  36. 02/34 am: release strbuf on error return in hg_patch_to_mail()Rene Scharfe, Aug 30, 2017
  37. 03/34 am: release strbuf after use in safe_to_abort()Rene Scharfe, Aug 30, 2017
  38. 09/34 convert: release strbuf on error return in filter_buffer_or_fd()Rene Scharfe, Aug 30, 2017
  39. 04/34 check-ref-format: release strbuf after use in check_ref_format_branch()Rene Scharfe, Aug 30, 2017
  40. 12/34 diff: release strbuf after use in show_stats()Rene Scharfe, Aug 30, 2017
  41. 11/34 diff: release strbuf after use in show_rename_copy()Rene Scharfe, Aug 30, 2017
  42. 21/34 refs: release strbuf on error return in write_pseudoref()Rene Scharfe, Aug 30, 2017
  43. 08/34 connect: release strbuf on error return in git_connect()Rene Scharfe, Aug 30, 2017
  44. 08/34 connect: release strbuf on error return in git_connect()Rene Scharfe, Aug 30, 2017
  45. 22/34 remote: release strbuf after use in read_remote_branches()Rene Scharfe, Aug 30, 2017
  46. 21/34 refs: release strbuf on error return in write_pseudoref()Rene Scharfe, Aug 30, 2017
  47. 25/34 send-pack: release strbuf on error return in send_pack()Rene Scharfe, Aug 30, 2017
  48. 23/34 remote: release strbuf after use in migrate_file()Rene Scharfe, Aug 30, 2017
  49. 24/34 remote: release strbuf after use in set_url()Rene Scharfe, Aug 30, 2017
  50. 27/34 shortlog: release strbuf after use in insert_one_record()Rene Scharfe, Aug 30, 2017
  51. Junio C HamanoSep 6, 2017
  52. Jeff KingSep 7, 2017
  53. Junio C HamanoSep 8, 2017
  54. Jeff KingSep 8, 2017
  55. Jeff KingSep 8, 2017
  56. Junio C HamanoSep 8, 2017
  57. shortlog: skip format/parse roundtrip for internal traversalJeff King, Sep 8, 2017
  58. René ScharfeSep 10, 2017
  59. Jeff KingSep 10, 2017
  60. 26/34 sha1_file: release strbuf on error return in index_path()Rene Scharfe, Aug 30, 2017
  61. 08/34 connect: release strbuf on error return in git_connect()Rene Scharfe, Aug 30, 2017
  62. 28/34 sequencer: release strbuf after use in save_head()Rene Scharfe, Aug 30, 2017
  63. 32/34 vcs-svn: release strbuf after use in end_revision()Rene Scharfe, Aug 30, 2017
  64. 34/34 wt-status: release strbuf after use in wt_longstatus_print_tracking()Rene Scharfe, Aug 30, 2017
  65. Junio C HamanoSep 6, 2017
  66. René ScharfeSep 10, 2017
  67. Junio C HamanoSep 10, 2017
  68. 31/34 utf8: release strbuf on error return in strbuf_utf8_replace()Rene Scharfe, Aug 30, 2017
  69. 33/34 wt-status: release strbuf after use in read_rebase_todolist()Rene Scharfe, Aug 30, 2017
  70. 21/34 refs: release strbuf on error return in write_pseudoref()Rene Scharfe, Aug 30, 2017
  71. 25/34 send-pack: release strbuf on error return in send_pack()Rene Scharfe, Aug 30, 2017
  72. 29/34 transport-helper: release strbuf after use in process_connect_service()Rene Scharfe, Aug 30, 2017
  73. 30/34 userdiff: release strbuf after use in userdiff_get_textconv()Rene Scharfe, Aug 30, 2017
  74. Stefan BellerAug 31, 2017
  75. Junio C HamanoSep 6, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.