Merge branch 'jk/tighten-alloc'
authorJunio C Hamano <gitster@pobox.com>
Wed, 26 Oct 2016 20:14:48 +0000 (13:14 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 26 Oct 2016 20:14:48 +0000 (13:14 -0700)
Protect our code from over-eager compilers.

* jk/tighten-alloc:
inline xalloc_flex() into FLEXPTR_ALLOC_MEM
avoid pointer arithmetic involving NULL in FLEX_ALLOC_MEM

1  2 
git-compat-util.h
diff --combined git-compat-util.h
index 43718dabae88062b39d65f2d6c1f5e35a6eb4800,36c4f3acf14947f5292d7d8a2260fc94b506dded..49ca28cb6b5aa9e06e16c16febde03a7a5e66959
@@@ -279,6 -279,9 +279,6 @@@ extern char *gitdirname(char *)
  #endif
  #include <openssl/ssl.h>
  #include <openssl/err.h>
 -#ifdef NO_HMAC_CTX_CLEANUP
 -#define HMAC_CTX_cleanup HMAC_cleanup
 -#endif
  #endif
  
  /* On most systems <netdb.h> would have given us this, but
  #define _PATH_DEFPATH "/usr/local/bin:/usr/bin:/bin"
  #endif
  
 -#ifndef STRIP_EXTENSION
 -#define STRIP_EXTENSION ""
 -#endif
 -
  #ifndef has_dos_drive_prefix
  static inline int git_has_dos_drive_prefix(const char *path)
  {
@@@ -409,9 -416,7 +409,9 @@@ extern NORETURN void usagef(const char 
  extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2)));
  extern NORETURN void die_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
  extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
 +extern int error_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
  extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
 +extern void warning_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
  
  #ifndef NO_OPENSSL
  #ifdef APPLE_COMMON_CRYPTO
@@@ -436,14 -441,10 +436,14 @@@ static inline int const_error(void
        return -1;
  }
  #define error(...) (error(__VA_ARGS__), const_error())
 +#define error_errno(...) (error_errno(__VA_ARGS__), const_error())
  #endif
  
  extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
  extern void set_error_routine(void (*routine)(const char *err, va_list params));
 +extern void (*get_error_routine(void))(const char *err, va_list params);
 +extern void set_warn_routine(void (*routine)(const char *warn, va_list params));
 +extern void (*get_warn_routine(void))(const char *warn, va_list params);
  extern void set_die_is_recursing_routine(int (*routine)(void));
  extern void set_error_handle(FILE *);
  
@@@ -477,23 -478,6 +477,23 @@@ static inline int skip_prefix(const cha
        return 0;
  }
  
 +/*
 + * Like skip_prefix, but promises never to read past "len" bytes of the input
 + * buffer, and returns the remaining number of bytes in "out" via "outlen".
 + */
 +static inline int skip_prefix_mem(const char *buf, size_t len,
 +                                const char *prefix,
 +                                const char **out, size_t *outlen)
 +{
 +      size_t prefix_len = strlen(prefix);
 +      if (prefix_len <= len && !memcmp(buf, prefix, prefix_len)) {
 +              *out = buf + prefix_len;
 +              *outlen = len - prefix_len;
 +              return 1;
 +      }
 +      return 0;
 +}
 +
  /*
   * If buf ends with suffix, return 1 and subtract the length of the suffix
   * from *len. Otherwise, return 0 and leave *len untouched.
@@@ -667,22 -651,10 +667,22 @@@ void *gitmemmem(const void *haystack, s
                  const void *needle, size_t needlelen);
  #endif
  
 +#ifdef OVERRIDE_STRDUP
 +#ifdef strdup
 +#undef strdup
 +#endif
 +#define strdup gitstrdup
 +char *gitstrdup(const char *s);
 +#endif
 +
  #ifdef NO_GETPAGESIZE
  #define getpagesize() sysconf(_SC_PAGESIZE)
  #endif
  
 +#ifndef O_CLOEXEC
 +#define O_CLOEXEC 0
 +#endif
 +
  #ifdef FREAD_READS_DIRECTORIES
  #ifdef fopen
  #undef fopen
@@@ -747,8 -719,8 +747,8 @@@ static inline size_t st_add(size_t a, s
                    (uintmax_t)a, (uintmax_t)b);
        return a + b;
  }
 -#define st_add3(a,b,c)   st_add((a),st_add((b),(c)))
 -#define st_add4(a,b,c,d) st_add((a),st_add3((b),(c),(d)))
 +#define st_add3(a,b,c)   st_add(st_add((a),(b)),(c))
 +#define st_add4(a,b,c,d) st_add(st_add3((a),(b),(c)),(d))
  
  static inline size_t st_mult(size_t a, size_t b)
  {
@@@ -801,14 -773,6 +801,14 @@@ extern FILE *fopen_for_writing(const ch
  #define ALLOC_ARRAY(x, alloc) (x) = xmalloc(st_mult(sizeof(*(x)), (alloc)))
  #define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), st_mult(sizeof(*(x)), (alloc)))
  
 +#define COPY_ARRAY(dst, src, n) copy_array((dst), (src), (n), sizeof(*(dst)) + \
 +      BUILD_ASSERT_OR_ZERO(sizeof(*(dst)) == sizeof(*(src))))
 +static inline void copy_array(void *dst, const void *src, size_t n, size_t size)
 +{
 +      if (n)
 +              memcpy(dst, src, st_mult(size, n));
 +}
 +
  /*
   * These functions help you allocate structs with flex arrays, and copy
   * the data directly into the array. For example, if you had:
   * times, and it must be assignable as an lvalue.
   */
  #define FLEX_ALLOC_MEM(x, flexname, buf, len) do { \
-       (x) = NULL; /* silence -Wuninitialized for offset calculation */ \
-       (x) = xalloc_flex(sizeof(*(x)), (char *)(&((x)->flexname)) - (char *)(x), (buf), (len)); \
+       size_t flex_array_len_ = (len); \
+       (x) = xcalloc(1, st_add3(sizeof(*(x)), flex_array_len_, 1)); \
+       memcpy((void *)(x)->flexname, (buf), flex_array_len_); \
  } while (0)
  #define FLEXPTR_ALLOC_MEM(x, ptrname, buf, len) do { \
-       (x) = xalloc_flex(sizeof(*(x)), sizeof(*(x)), (buf), (len)); \
+       size_t flex_array_len_ = (len); \
+       (x) = xcalloc(1, st_add3(sizeof(*(x)), flex_array_len_, 1)); \
+       memcpy((x) + 1, (buf), flex_array_len_); \
        (x)->ptrname = (void *)((x)+1); \
  } while(0)
  #define FLEX_ALLOC_STR(x, flexname, str) \
  #define FLEXPTR_ALLOC_STR(x, ptrname, str) \
        FLEXPTR_ALLOC_MEM((x), ptrname, (str), strlen(str))
  
- static inline void *xalloc_flex(size_t base_len, size_t offset,
-                               const void *src, size_t src_len)
- {
-       unsigned char *ret = xcalloc(1, st_add3(base_len, src_len, 1));
-       memcpy(ret + offset, src, src_len);
-       return ret;
- }
  static inline char *xstrdup_or_null(const char *str)
  {
        return str ? xstrdup(str) : NULL;
@@@ -985,27 -944,6 +980,27 @@@ void git_qsort(void *base, size_t nmemb
  #define qsort git_qsort
  #endif
  
 +#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
 +static inline void sane_qsort(void *base, size_t nmemb, size_t size,
 +                            int(*compar)(const void *, const void *))
 +{
 +      if (nmemb > 1)
 +              qsort(base, nmemb, size, compar);
 +}
 +
 +#ifndef REG_STARTEND
 +#error "Git requires REG_STARTEND support. Compile with NO_REGEX=NeedsStartEnd"
 +#endif
 +
 +static inline int regexec_buf(const regex_t *preg, const char *buf, size_t size,
 +                            size_t nmatch, regmatch_t pmatch[], int eflags)
 +{
 +      assert(nmatch > 0 && pmatch);
 +      pmatch[0].rm_so = 0;
 +      pmatch[0].rm_eo = size;
 +      return regexec(preg, buf, nmatch, pmatch, eflags | REG_STARTEND);
 +}
 +
  #ifndef DIR_HAS_BSD_GROUP_SEMANTICS
  # define FORCE_DIR_SET_GID S_ISGID
  #else
@@@ -1107,5 -1045,3 +1102,5 @@@ struct tm *git_gmtime_r(const time_t *
  #endif
  
  #endif
 +
 +extern int cmd_main(int, const char **);