Merge branch 'mh/strbuf-read-file-returns-ssize-t'
authorJunio C Hamano <gitster@pobox.com>
Mon, 13 Jul 2015 21:00:27 +0000 (14:00 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 13 Jul 2015 21:00:27 +0000 (14:00 -0700)
Avoid possible ssize_t to int truncation.

* mh/strbuf-read-file-returns-ssize-t:
strbuf: strbuf_read_file() should return ssize_t

1  2 
strbuf.c
strbuf.h
diff --combined strbuf.c
index 0d4f4e54ec1ff1f0d37155e8049476d802a7c7e5,b4da9f5d05fc1f22f8910a21d8e352f2e5e9673f..bbaf32eef6b0b36ea52390be3aee2ffab7f24f13
+++ b/strbuf.c
@@@ -435,47 -435,6 +435,47 @@@ int strbuf_getcwd(struct strbuf *sb
        return -1;
  }
  
 +#ifdef HAVE_GETDELIM
 +int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
 +{
 +      ssize_t r;
 +
 +      if (feof(fp))
 +              return EOF;
 +
 +      strbuf_reset(sb);
 +
 +      /* Translate slopbuf to NULL, as we cannot call realloc on it */
 +      if (!sb->alloc)
 +              sb->buf = NULL;
 +      r = getdelim(&sb->buf, &sb->alloc, term, fp);
 +
 +      if (r > 0) {
 +              sb->len = r;
 +              return 0;
 +      }
 +      assert(r == -1);
 +
 +      /*
 +       * Normally we would have called xrealloc, which will try to free
 +       * memory and recover. But we have no way to tell getdelim() to do so.
 +       * Worse, we cannot try to recover ENOMEM ourselves, because we have
 +       * no idea how many bytes were read by getdelim.
 +       *
 +       * Dying here is reasonable. It mirrors what xrealloc would do on
 +       * catastrophic memory failure. We skip the opportunity to free pack
 +       * memory and retry, but that's unlikely to help for a malloc small
 +       * enough to hold a single line of input, anyway.
 +       */
 +      if (errno == ENOMEM)
 +              die("Out of memory, getdelim failed");
 +
 +      /* Restore slopbuf that we moved out of the way before */
 +      if (!sb->buf)
 +              strbuf_init(sb, 0);
 +      return EOF;
 +}
 +#else
  int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
  {
        int ch;
                return EOF;
  
        strbuf_reset(sb);
 -      while ((ch = fgetc(fp)) != EOF) {
 -              strbuf_grow(sb, 1);
 +      flockfile(fp);
 +      while ((ch = getc_unlocked(fp)) != EOF) {
 +              if (!strbuf_avail(sb))
 +                      strbuf_grow(sb, 1);
                sb->buf[sb->len++] = ch;
                if (ch == term)
                        break;
        }
 +      funlockfile(fp);
        if (ch == EOF && sb->len == 0)
                return EOF;
  
        sb->buf[sb->len] = '\0';
        return 0;
  }
 +#endif
  
  int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
  {
@@@ -526,9 -481,10 +526,10 @@@ int strbuf_getwholeline_fd(struct strbu
        return 0;
  }
  
int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
ssize_t strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
  {
-       int fd, len;
+       int fd;
+       ssize_t len;
  
        fd = open(path, O_RDONLY);
        if (fd < 0)
diff --combined strbuf.h
index 01c5c6371b8e43686f335704a67a59a1d82dbe3b,1ea9d0bdeb0980dcaa8670aa43e4ff703fd9d6b8..4a48c0031a7c0df6a7efdb2151d5701dd256fa28
+++ b/strbuf.h
@@@ -205,8 -205,7 +205,8 @@@ extern int strbuf_cmp(const struct strb
   */
  static inline void strbuf_addch(struct strbuf *sb, int c)
  {
 -      strbuf_grow(sb, 1);
 +      if (!strbuf_avail(sb))
 +              strbuf_grow(sb, 1);
        sb->buf[sb->len++] = c;
        sb->buf[sb->len] = '\0';
  }
@@@ -365,7 -364,7 +365,7 @@@ extern ssize_t strbuf_read(struct strbu
   * Read the contents of a file, specified by its path. The third argument
   * can be used to give a hint about the file size, to avoid reallocs.
   */
- extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);
+ extern ssize_t strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);
  
  /**
   * Read the target of a symbolic link, specified by its path.  The third