@matheusbsbs / matheus-bagliano / commits / 8ca7880356
Fork 0

for_each_recent_reflog_ent(): use strbuf, fix offset handling

As Vladimir reported, "git log -g refs/stash" surprisingly showed the reflog of HEAD if the message in the reflog file was too long. To fix this, convert for_each_recent_reflog_ent() to use strbuf_getwholeline() instead of fgets(), for safety and to avoid any size limits for reflog entries. Also reverse the logic of the part of the function that only looks at file tails. It used to close the file if fgets() succeeded. The following fgets() call in the while loop was likely to fail in this case, too, so passing an offset to for_each_recent_reflog_ent() never worked. Change it to error out if strbuf_getwholeline() fails instead. Reported-by: Vladimir Panteleev <vladimir@thecybershadow.net> Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Mar 13, 2010 at 18:37 UTC 8ca788035644f2aaf7a951272ae16a7bd319554c
1 file changed +12 -10
refs.c
+12 -10
@@ -1574,7 +1574,7 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs,
1574 {
1575 const char *logfile;
1576 FILE *logfp;
1577 - char buf[1024];
1577 + struct strbuf sb = STRBUF_INIT;
1578 int ret = 0;
1579
1580 logfile = git_path("logs/%s", ref);
@@ -1587,24 +1587,24 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs,
1587 if (fstat(fileno(logfp), &statbuf) ||
1588 statbuf.st_size < ofs ||
1589 fseek(logfp, -ofs, SEEK_END) ||
1590 - fgets(buf, sizeof(buf), logfp)) {
1590 + strbuf_getwholeline(&sb, logfp, '\n')) {
1591 fclose(logfp);
1592 + strbuf_release(&sb);
1593 return -1;
1594 }
1595 }
1596
1596 - while (fgets(buf, sizeof(buf), logfp)) {
1597 + while (!strbuf_getwholeline(&sb, logfp, '\n')) {
1598 unsigned char osha1[20], nsha1[20];
1599 char *email_end, *message;
1600 unsigned long timestamp;
1600 - int len, tz;
1601 + int tz;
1602
1603 /* old SP new SP name <email> SP time TAB msg LF */
1603 - len = strlen(buf);
1604 - if (len < 83 || buf[len-1] != '\n' ||
1605 - get_sha1_hex(buf, osha1) || buf[40] != ' ' ||
1606 - get_sha1_hex(buf + 41, nsha1) || buf[81] != ' ' ||
1607 - !(email_end = strchr(buf + 82, '>')) ||
1604 + if (sb.len < 83 || sb.buf[sb.len - 1] != '\n' ||
1605 + get_sha1_hex(sb.buf, osha1) || sb.buf[40] != ' ' ||
1606 + get_sha1_hex(sb.buf + 41, nsha1) || sb.buf[81] != ' ' ||
1607 + !(email_end = strchr(sb.buf + 82, '>')) ||
1608 email_end[1] != ' ' ||
1609 !(timestamp = strtoul(email_end + 2, &message, 10)) ||
1610 !message || message[0] != ' ' ||
@@ -1618,11 +1618,13 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs,
1618 message += 6;
1619 else
1620 message += 7;
1621 - ret = fn(osha1, nsha1, buf+82, timestamp, tz, message, cb_data);
1621 + ret = fn(osha1, nsha1, sb.buf + 82, timestamp, tz, message,
1622 + cb_data);
1623 if (ret)
1624 break;
1625 }
1626 fclose(logfp);
1627 + strbuf_release(&sb);
1628 return ret;
1629 }
1630