Commits

Anonymous committed 5914f2d

fetch: create status table using strbuf

When we fetch from a remote, we print a status table like:

From url
* [new branch] foo -> origin/foo

We create this table in a static buffer using sprintf. If
the remote refnames are long, they can overflow this buffer
and smash the stack.

Instead, let's use a strbuf to build the string.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

Comments (0)

Files changed (1)

 
 static int update_local_ref(struct ref *ref,
 			    const char *remote,
-			    char *display)
+			    struct strbuf *display)
 {
 	struct commit *current = NULL, *updated;
 	enum object_type type;
 	struct branch *current_branch = branch_get(NULL);
 	const char *pretty_ref = prettify_refname(ref->name);
 
-	*display = 0;
 	type = sha1_object_info(ref->new_sha1, NULL);
 	if (type < 0)
 		die(_("object %s not found"), sha1_to_hex(ref->new_sha1));
 
 	if (!hashcmp(ref->old_sha1, ref->new_sha1)) {
 		if (verbosity > 0)
-			sprintf(display, "= %-*s %-*s -> %s", TRANSPORT_SUMMARY_WIDTH,
-				_("[up to date]"), REFCOL_WIDTH, remote,
-				pretty_ref);
+			strbuf_addf(display, "= %-*s %-*s -> %s",
+				    TRANSPORT_SUMMARY_WIDTH,
+				    _("[up to date]"), REFCOL_WIDTH,
+				    remote, pretty_ref);
 		return 0;
 	}
 
 		 * If this is the head, and it's not okay to update
 		 * the head, and the old value of the head isn't empty...
 		 */
-		sprintf(display, _("! %-*s %-*s -> %s  (can't fetch in current branch)"),
-			TRANSPORT_SUMMARY_WIDTH, _("[rejected]"), REFCOL_WIDTH, remote,
-			pretty_ref);
+		strbuf_addf(display,
+			    _("! %-*s %-*s -> %s  (can't fetch in current branch)"),
+			    TRANSPORT_SUMMARY_WIDTH, _("[rejected]"),
+			    REFCOL_WIDTH, remote, pretty_ref);
 		return 1;
 	}
 
 	    !prefixcmp(ref->name, "refs/tags/")) {
 		int r;
 		r = s_update_ref("updating tag", ref, 0);
-		sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : '-',
-			TRANSPORT_SUMMARY_WIDTH, _("[tag update]"), REFCOL_WIDTH, remote,
-			pretty_ref, r ? _("  (unable to update local ref)") : "");
+		strbuf_addf(display, "%c %-*s %-*s -> %s%s",
+			    r ? '!' : '-',
+			    TRANSPORT_SUMMARY_WIDTH, _("[tag update]"),
+			    REFCOL_WIDTH, remote, pretty_ref,
+			    r ? _("  (unable to update local ref)") : "");
 		return r;
 	}
 
 		}
 
 		r = s_update_ref(msg, ref, 0);
-		sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : '*',
-			TRANSPORT_SUMMARY_WIDTH, what, REFCOL_WIDTH, remote, pretty_ref,
-			r ? _("  (unable to update local ref)") : "");
+		strbuf_addf(display, "%c %-*s %-*s -> %s%s",
+			    r ? '!' : '*',
+			    TRANSPORT_SUMMARY_WIDTH, what,
+			    REFCOL_WIDTH, remote, pretty_ref,
+			    r ? _("  (unable to update local ref)") : "");
 		return r;
 	}
 
 		    (recurse_submodules != RECURSE_SUBMODULES_ON))
 			check_for_new_submodule_commits(ref->new_sha1);
 		r = s_update_ref("fast-forward", ref, 1);
-		sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : ' ',
-			TRANSPORT_SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
-			pretty_ref, r ? _("  (unable to update local ref)") : "");
+		strbuf_addf(display, "%c %-*s %-*s -> %s%s",
+			    r ? '!' : ' ',
+			    TRANSPORT_SUMMARY_WIDTH, quickref,
+			    REFCOL_WIDTH, remote, pretty_ref,
+			    r ? _("  (unable to update local ref)") : "");
 		return r;
 	} else if (force || ref->force) {
 		char quickref[84];
 		    (recurse_submodules != RECURSE_SUBMODULES_ON))
 			check_for_new_submodule_commits(ref->new_sha1);
 		r = s_update_ref("forced-update", ref, 1);
-		sprintf(display, "%c %-*s %-*s -> %s  (%s)", r ? '!' : '+',
-			TRANSPORT_SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
-			pretty_ref,
-			r ? _("unable to update local ref") : _("forced update"));
+		strbuf_addf(display, "%c %-*s %-*s -> %s  (%s)",
+			    r ? '!' : '+',
+			    TRANSPORT_SUMMARY_WIDTH, quickref,
+			    REFCOL_WIDTH, remote, pretty_ref,
+			    r ? _("unable to update local ref") : _("forced update"));
 		return r;
 	} else {
-		sprintf(display, "! %-*s %-*s -> %s  %s",
-			TRANSPORT_SUMMARY_WIDTH, _("[rejected]"), REFCOL_WIDTH, remote,
-			pretty_ref, _("(non-fast-forward)"));
+		strbuf_addf(display, "! %-*s %-*s -> %s  %s",
+			    TRANSPORT_SUMMARY_WIDTH, _("[rejected]"),
+			    REFCOL_WIDTH, remote, pretty_ref,
+			    _("(non-fast-forward)"));
 		return 1;
 	}
 }
 {
 	FILE *fp;
 	struct commit *commit;
-	int url_len, i, note_len, shown_url = 0, rc = 0;
-	char note[1024];
+	int url_len, i, shown_url = 0, rc = 0;
+	struct strbuf note = STRBUF_INIT;
 	const char *what, *kind;
 	struct ref *rm;
 	char *url, *filename = dry_run ? "/dev/null" : git_path("FETCH_HEAD");
 		if (4 < i && !strncmp(".git", url + i - 3, 4))
 			url_len = i - 3;
 
-		note_len = 0;
+		strbuf_reset(&note);
 		if (*what) {
 			if (*kind)
-				note_len += sprintf(note + note_len, "%s ",
-						    kind);
-			note_len += sprintf(note + note_len, "'%s' of ", what);
+				strbuf_addf(&note, "%s ", kind);
+			strbuf_addf(&note, "'%s' of ", what);
 		}
-		note[note_len] = '\0';
 		fprintf(fp, "%s\t%s\t%s",
 			sha1_to_hex(commit ? commit->object.sha1 :
 				    rm->old_sha1),
 			rm->merge ? "" : "not-for-merge",
-			note);
+			note.buf);
 		for (i = 0; i < url_len; ++i)
 			if ('\n' == url[i])
 				fputs("\\n", fp);
 				fputc(url[i], fp);
 		fputc('\n', fp);
 
+		strbuf_reset(&note);
 		if (ref) {
-			rc |= update_local_ref(ref, what, note);
+			rc |= update_local_ref(ref, what, &note);
 			free(ref);
 		} else
-			sprintf(note, "* %-*s %-*s -> FETCH_HEAD",
-				TRANSPORT_SUMMARY_WIDTH, *kind ? kind : "branch",
-				 REFCOL_WIDTH, *what ? what : "HEAD");
-		if (*note) {
+			strbuf_addf(&note, "* %-*s %-*s -> FETCH_HEAD",
+				    TRANSPORT_SUMMARY_WIDTH,
+				    *kind ? kind : "branch",
+				    REFCOL_WIDTH,
+				    *what ? what : "HEAD");
+		if (note.len) {
 			if (verbosity >= 0 && !shown_url) {
 				fprintf(stderr, _("From %.*s\n"),
 						url_len, url);
 				shown_url = 1;
 			}
 			if (verbosity >= 0)
-				fprintf(stderr, " %s\n", note);
+				fprintf(stderr, " %s\n", note.buf);
 		}
 	}
 	free(url);
 		error(_("some local refs could not be updated; try running\n"
 		      " 'git remote prune %s' to remove any old, conflicting "
 		      "branches"), remote_name);
+	strbuf_release(&note);
 	return rc;
 }
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.