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>
Jeff King committed
Dec 8, 2011 at 03:43 UTC
5914f2d057c259668695bccab8e9bec3a4bead53
1 file changed
+49
-38
builtin/fetch.c
+49
-38
@@ -239,23 +239,23 @@ static int s_update_ref(const char *action,
239
240
static int update_local_ref(struct ref *ref,
241
const char *remote,
242
- char *display)
242
+ struct strbuf *display)
243
{
244
struct commit *current = NULL, *updated;
245
enum object_type type;
246
struct branch *current_branch = branch_get(NULL);
247
const char *pretty_ref = prettify_refname(ref->name);
248
249
- *display = 0;
249
type = sha1_object_info(ref->new_sha1, NULL);
250
if (type < 0)
251
die(_("object %s not found"), sha1_to_hex(ref->new_sha1));
252
253
if (!hashcmp(ref->old_sha1, ref->new_sha1)) {
254
if (verbosity > 0)
256
- sprintf(display, "= %-*s %-*s -> %s", TRANSPORT_SUMMARY_WIDTH,
257
- _("[up to date]"), REFCOL_WIDTH, remote,
258
- pretty_ref);
255
+ strbuf_addf(display, "= %-*s %-*s -> %s",
256
+ TRANSPORT_SUMMARY_WIDTH,
257
+ _("[up to date]"), REFCOL_WIDTH,
258
+ remote, pretty_ref);
259
return 0;
260
}
261
@@ -267,9 +267,10 @@ static int update_local_ref(struct ref *ref,
267
* If this is the head, and it's not okay to update
268
* the head, and the old value of the head isn't empty...
269
*/
270
- sprintf(display, _("! %-*s %-*s -> %s (can't fetch in current branch)"),
271
- TRANSPORT_SUMMARY_WIDTH, _("[rejected]"), REFCOL_WIDTH, remote,
272
- pretty_ref);
270
+ strbuf_addf(display,
271
+ _("! %-*s %-*s -> %s (can't fetch in current branch)"),
272
+ TRANSPORT_SUMMARY_WIDTH, _("[rejected]"),
273
+ REFCOL_WIDTH, remote, pretty_ref);
274
return 1;
275
}
276
@@ -277,9 +278,11 @@ static int update_local_ref(struct ref *ref,
278
!prefixcmp(ref->name, "refs/tags/")) {
279
int r;
280
r = s_update_ref("updating tag", ref, 0);
280
- sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : '-',
281
- TRANSPORT_SUMMARY_WIDTH, _("[tag update]"), REFCOL_WIDTH, remote,
282
- pretty_ref, r ? _(" (unable to update local ref)") : "");
281
+ strbuf_addf(display, "%c %-*s %-*s -> %s%s",
282
+ r ? '!' : '-',
283
+ TRANSPORT_SUMMARY_WIDTH, _("[tag update]"),
284
+ REFCOL_WIDTH, remote, pretty_ref,
285
+ r ? _(" (unable to update local ref)") : "");
286
return r;
287
}
288
@@ -302,9 +305,11 @@ static int update_local_ref(struct ref *ref,
305
}
306
307
r = s_update_ref(msg, ref, 0);
305
- sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : '*',
306
- TRANSPORT_SUMMARY_WIDTH, what, REFCOL_WIDTH, remote, pretty_ref,
307
- r ? _(" (unable to update local ref)") : "");
308
+ strbuf_addf(display, "%c %-*s %-*s -> %s%s",
309
+ r ? '!' : '*',
310
+ TRANSPORT_SUMMARY_WIDTH, what,
311
+ REFCOL_WIDTH, remote, pretty_ref,
312
+ r ? _(" (unable to update local ref)") : "");
313
return r;
314
}
315
@@ -318,9 +323,11 @@ static int update_local_ref(struct ref *ref,
323
(recurse_submodules != RECURSE_SUBMODULES_ON))
324
check_for_new_submodule_commits(ref->new_sha1);
325
r = s_update_ref("fast-forward", ref, 1);
321
- sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : ' ',
322
- TRANSPORT_SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
323
- pretty_ref, r ? _(" (unable to update local ref)") : "");
326
+ strbuf_addf(display, "%c %-*s %-*s -> %s%s",
327
+ r ? '!' : ' ',
328
+ TRANSPORT_SUMMARY_WIDTH, quickref,
329
+ REFCOL_WIDTH, remote, pretty_ref,
330
+ r ? _(" (unable to update local ref)") : "");
331
return r;
332
} else if (force || ref->force) {
333
char quickref[84];
@@ -332,15 +339,17 @@ static int update_local_ref(struct ref *ref,
339
(recurse_submodules != RECURSE_SUBMODULES_ON))
340
check_for_new_submodule_commits(ref->new_sha1);
341
r = s_update_ref("forced-update", ref, 1);
335
- sprintf(display, "%c %-*s %-*s -> %s (%s)", r ? '!' : '+',
336
- TRANSPORT_SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
337
- pretty_ref,
338
- r ? _("unable to update local ref") : _("forced update"));
342
+ strbuf_addf(display, "%c %-*s %-*s -> %s (%s)",
343
+ r ? '!' : '+',
344
+ TRANSPORT_SUMMARY_WIDTH, quickref,
345
+ REFCOL_WIDTH, remote, pretty_ref,
346
+ r ? _("unable to update local ref") : _("forced update"));
347
return r;
348
} else {
341
- sprintf(display, "! %-*s %-*s -> %s %s",
342
- TRANSPORT_SUMMARY_WIDTH, _("[rejected]"), REFCOL_WIDTH, remote,
343
- pretty_ref, _("(non-fast-forward)"));
349
+ strbuf_addf(display, "! %-*s %-*s -> %s %s",
350
+ TRANSPORT_SUMMARY_WIDTH, _("[rejected]"),
351
+ REFCOL_WIDTH, remote, pretty_ref,
352
+ _("(non-fast-forward)"));
353
return 1;
354
}
355
}
@@ -350,8 +359,8 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
359
{
360
FILE *fp;
361
struct commit *commit;
353
- int url_len, i, note_len, shown_url = 0, rc = 0;
354
- char note[1024];
362
+ int url_len, i, shown_url = 0, rc = 0;
363
+ struct strbuf note = STRBUF_INIT;
364
const char *what, *kind;
365
struct ref *rm;
366
char *url, *filename = dry_run ? "/dev/null" : git_path("FETCH_HEAD");
@@ -407,19 +416,17 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
416
if (4 < i && !strncmp(".git", url + i - 3, 4))
417
url_len = i - 3;
418
410
- note_len = 0;
419
+ strbuf_reset(¬e);
420
if (*what) {
421
if (*kind)
413
- note_len += sprintf(note + note_len, "%s ",
414
- kind);
415
- note_len += sprintf(note + note_len, "'%s' of ", what);
422
+ strbuf_addf(¬e, "%s ", kind);
423
+ strbuf_addf(¬e, "'%s' of ", what);
424
}
417
- note[note_len] = '\0';
425
fprintf(fp, "%s\t%s\t%s",
426
sha1_to_hex(commit ? commit->object.sha1 :
427
rm->old_sha1),
428
rm->merge ? "" : "not-for-merge",
422
- note);
429
+ note.buf);
430
for (i = 0; i < url_len; ++i)
431
if ('\n' == url[i])
432
fputs("\\n", fp);
@@ -427,21 +434,24 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
434
fputc(url[i], fp);
435
fputc('\n', fp);
436
437
+ strbuf_reset(¬e);
438
if (ref) {
431
- rc |= update_local_ref(ref, what, note);
439
+ rc |= update_local_ref(ref, what, ¬e);
440
free(ref);
441
} else
434
- sprintf(note, "* %-*s %-*s -> FETCH_HEAD",
435
- TRANSPORT_SUMMARY_WIDTH, *kind ? kind : "branch",
436
- REFCOL_WIDTH, *what ? what : "HEAD");
437
- if (*note) {
442
+ strbuf_addf(¬e, "* %-*s %-*s -> FETCH_HEAD",
443
+ TRANSPORT_SUMMARY_WIDTH,
444
+ *kind ? kind : "branch",
445
+ REFCOL_WIDTH,
446
+ *what ? what : "HEAD");
447
+ if (note.len) {
448
if (verbosity >= 0 && !shown_url) {
449
fprintf(stderr, _("From %.*s\n"),
450
url_len, url);
451
shown_url = 1;
452
}
453
if (verbosity >= 0)
444
- fprintf(stderr, " %s\n", note);
454
+ fprintf(stderr, " %s\n", note.buf);
455
}
456
}
457
free(url);
@@ -450,6 +460,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
460
error(_("some local refs could not be updated; try running\n"
461
" 'git remote prune %s' to remove any old, conflicting "
462
"branches"), remote_name);
463
+ strbuf_release(¬e);
464
return rc;
465
}
466