Skip to content

Commit 8ca7880

Browse files
René Scharfegitster
authored andcommitted
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 <[email protected]> Signed-off-by: Rene Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 34b383e commit 8ca7880

File tree

1 file changed

+12
-10
lines changed

1 file changed

+12
-10
lines changed

refs.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,7 +1574,7 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs,
15741574
{
15751575
const char *logfile;
15761576
FILE *logfp;
1577-
char buf[1024];
1577+
struct strbuf sb = STRBUF_INIT;
15781578
int ret = 0;
15791579

15801580
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,
15871587
if (fstat(fileno(logfp), &statbuf) ||
15881588
statbuf.st_size < ofs ||
15891589
fseek(logfp, -ofs, SEEK_END) ||
1590-
fgets(buf, sizeof(buf), logfp)) {
1590+
strbuf_getwholeline(&sb, logfp, '\n')) {
15911591
fclose(logfp);
1592+
strbuf_release(&sb);
15921593
return -1;
15931594
}
15941595
}
15951596

1596-
while (fgets(buf, sizeof(buf), logfp)) {
1597+
while (!strbuf_getwholeline(&sb, logfp, '\n')) {
15971598
unsigned char osha1[20], nsha1[20];
15981599
char *email_end, *message;
15991600
unsigned long timestamp;
1600-
int len, tz;
1601+
int tz;
16011602

16021603
/* 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, '>')) ||
16081608
email_end[1] != ' ' ||
16091609
!(timestamp = strtoul(email_end + 2, &message, 10)) ||
16101610
!message || message[0] != ' ' ||
@@ -1618,11 +1618,13 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs,
16181618
message += 6;
16191619
else
16201620
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);
16221623
if (ret)
16231624
break;
16241625
}
16251626
fclose(logfp);
1627+
strbuf_release(&sb);
16261628
return ret;
16271629
}
16281630

0 commit comments

Comments
 (0)