From: Junio C Hamano Date: Wed, 27 Dec 2017 19:16:24 +0000 (-0800) Subject: Merge branch 'rs/strbuf-read-once-reset-length' X-Git-Tag: v2.16.0-rc0~31 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/a13e45f1e7e6fc02d4e10e0589578a77e84f3ffb?hp=-c Merge branch 'rs/strbuf-read-once-reset-length' Leakfix. * rs/strbuf-read-once-reset-length: strbuf: release memory on read error in strbuf_read_once() --- a13e45f1e7e6fc02d4e10e0589578a77e84f3ffb diff --combined strbuf.c index 323c49ceb3,0809bca256..ac5a7ab62d --- a/strbuf.c +++ b/strbuf.c @@@ -204,6 -204,13 +204,6 @@@ void strbuf_addbuf(struct strbuf *sb, c strbuf_setlen(sb, sb->len + sb2->len); } -void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len) -{ - strbuf_grow(sb, len); - memcpy(sb->buf + sb->len, sb->buf + pos, len); - strbuf_setlen(sb, sb->len + len); -} - void strbuf_addchars(struct strbuf *sb, int c, size_t n) { strbuf_grow(sb, n); @@@ -386,12 -393,15 +386,15 @@@ ssize_t strbuf_read(struct strbuf *sb, ssize_t strbuf_read_once(struct strbuf *sb, int fd, size_t hint) { + size_t oldalloc = sb->alloc; ssize_t cnt; strbuf_grow(sb, hint ? hint : 8192); cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1); if (cnt > 0) strbuf_setlen(sb, sb->len + cnt); + else if (oldalloc == 0) + strbuf_release(sb); return cnt; } @@@ -442,17 -452,6 +445,17 @@@ int strbuf_getcwd(struct strbuf *sb strbuf_setlen(sb, strlen(sb->buf)); return 0; } + + /* + * If getcwd(3) is implemented as a syscall that falls + * back to a regular lookup using readdir(3) etc. then + * we may be able to avoid EACCES by providing enough + * space to the syscall as it's not necessarily bound + * to the same restrictions as the fallback. + */ + if (errno == EACCES && guessed_len < PATH_MAX) + continue; + if (errno != ERANGE) break; } @@@ -476,7 -475,6 +479,7 @@@ int strbuf_getwholeline(struct strbuf * /* Translate slopbuf to NULL, as we cannot call realloc on it */ if (!sb->alloc) sb->buf = NULL; + errno = 0; r = getdelim(&sb->buf, &sb->alloc, term, fp); if (r > 0) { @@@ -779,47 -777,14 +782,47 @@@ char *xstrfmt(const char *fmt, ... return ret; } -void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm) +void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm, + int tz_offset, int suppress_tz_name) { + struct strbuf munged_fmt = STRBUF_INIT; size_t hint = 128; size_t len; if (!*fmt) return; + /* + * There is no portable way to pass timezone information to + * strftime, so we handle %z and %Z here. + */ + for (;;) { + const char *percent = strchrnul(fmt, '%'); + strbuf_add(&munged_fmt, fmt, percent - fmt); + if (!*percent) + break; + fmt = percent + 1; + switch (*fmt) { + case '%': + strbuf_addstr(&munged_fmt, "%%"); + fmt++; + break; + case 'z': + strbuf_addf(&munged_fmt, "%+05d", tz_offset); + fmt++; + break; + case 'Z': + if (suppress_tz_name) { + fmt++; + break; + } + /* FALLTHROUGH */ + default: + strbuf_addch(&munged_fmt, '%'); + } + } + fmt = munged_fmt.buf; + strbuf_grow(sb, hint); len = strftime(sb->buf + sb->len, sb->alloc - sb->len, fmt, tm); @@@ -831,16 -796,17 +834,16 @@@ * output contains at least one character, and then drop the extra * character before returning. */ - struct strbuf munged_fmt = STRBUF_INIT; - strbuf_addf(&munged_fmt, "%s ", fmt); + strbuf_addch(&munged_fmt, ' '); while (!len) { hint *= 2; strbuf_grow(sb, hint); len = strftime(sb->buf + sb->len, sb->alloc - sb->len, munged_fmt.buf, tm); } - strbuf_release(&munged_fmt); len--; /* drop munged space */ } + strbuf_release(&munged_fmt); strbuf_setlen(sb, sb->len + len); }