Merge branch 'rs/strbuf-getwholeline-fix' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 18 Oct 2017 05:18:57 +0000 (14:18 +0900)
committerJunio C Hamano <gitster@pobox.com>
Wed, 18 Oct 2017 05:18:58 +0000 (14:18 +0900)
A helper function to read a single whole line into strbuf
mistakenly triggered OOM error at EOF under certain conditions,
which has been fixed.

* rs/strbuf-getwholeline-fix:
strbuf: clear errno before calling getdelim(3)

1  2 
strbuf.c
diff --combined strbuf.c
index 89d22e3b0903a220fa958b8d912607828ab2a9ba,977acba31b6cecc6aa6e8f8070d2faee2a93529a..323c49ceb35cb053434248df869578e649ccadc0
+++ 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);
@@@ -442,17 -449,6 +442,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,6 -472,7 +476,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) {
@@@ -778,47 -775,14 +779,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);
  
                 * 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);
  }