Merge branch 'ep/do-not-feed-a-pointer-to-array-size'
authorJunio C Hamano <gitster@pobox.com>
Mon, 11 May 2015 21:24:00 +0000 (14:24 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 11 May 2015 21:24:00 +0000 (14:24 -0700)
Catch a programmer mistake to feed a pointer not an array to
ARRAY_SIZE() macro, by using a couple of GCC extensions.

* ep/do-not-feed-a-pointer-to-array-size:
git-compat-util.h: implement a different ARRAY_SIZE macro for for safely deriving the size of array

1  2 
git-compat-util.h
diff --combined git-compat-util.h
index 685a0a4063edd2a6700533df7faa2a910df60bb3,7fad5aad9f4909d1120dfba5ffb958ddd831d2fa..b7a97fbe8300532505b9d63dace2a3f76d8e04e2
@@@ -3,6 -3,23 +3,23 @@@
  
  #define _FILE_OFFSET_BITS 64
  
+ /* Derived from Linux "Features Test Macro" header
+  * Convenience macros to test the versions of gcc (or
+  * a compatible compiler).
+  * Use them like this:
+  *  #if GIT_GNUC_PREREQ (2,8)
+  *   ... code requiring gcc 2.8 or later ...
+  *  #endif
+ */
+ #if defined(__GNUC__) && defined(__GNUC_MINOR__)
+ # define GIT_GNUC_PREREQ(maj, min) \
+       ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+ #else
+  #define GIT_GNUC_PREREQ(maj, min) 0
+ #endif
  #ifndef FLEX_ARRAY
  /*
   * See if our compiler is known to support flexible array members.
  #endif
  #endif
  
- #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+ /*
+  * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression.
+  * @cond: the compile-time condition which must be true.
+  *
+  * Your compile will fail if the condition isn't true, or can't be evaluated
+  * by the compiler.  This can be used in an expression: its value is "0".
+  *
+  * Example:
+  *    #define foo_to_char(foo)                                        \
+  *             ((char *)(foo)                                         \
+  *              + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0))
+  */
+ #define BUILD_ASSERT_OR_ZERO(cond) \
+       (sizeof(char [1 - 2*!(cond)]) - 1)
+ #if defined(__GNUC__) && (__GNUC__ >= 3)
+ # if GIT_GNUC_PREREQ(3, 1)
+  /* &arr[0] degrades to a pointer: a different type from an array */
+ # define BARF_UNLESS_AN_ARRAY(arr)                                            \
+       BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(__typeof__(arr), \
+                                                          __typeof__(&(arr)[0])))
+ # else
+ #  define BARF_UNLESS_AN_ARRAY(arr) 0
+ # endif
+ #endif
+ /*
+  * ARRAY_SIZE - get the number of elements in a visible array
+  *  <at> x: the array whose size you want.
+  *
+  * This does not work on pointers, or arrays declared as [], or
+  * function parameters.  With correct compiler support, such usage
+  * will cause a build error (see the build_assert_or_zero macro).
+  */
+ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]) + BARF_UNLESS_AN_ARRAY(x))
  #define bitsizeof(x)  (CHAR_BIT * sizeof(x))
  
  #define maximum_signed_value_of_type(a) \
  # endif
  #elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
        !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
 -      !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__)
 +      !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
 +      !defined(__CYGWIN__)
  #define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
  #define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
  #endif
  #else
  #include <poll.h>
  #endif
 +#ifdef HAVE_BSD_SYSCTL
 +#include <sys/sysctl.h>
 +#endif
  
  #if defined(__MINGW32__)
  /* pull in Windows compatibility stuff */
  typedef long intptr_t;
  typedef unsigned long uintptr_t;
  #endif
 -#if defined(__CYGWIN__)
 -#undef _XOPEN_SOURCE
 -#include <grp.h>
 -#define _XOPEN_SOURCE 600
 -#else
  #undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
  #include <grp.h>
  #define _ALL_SOURCE 1
  #endif
 -#endif
  
  /* used on Mac OS X */
  #ifdef PRECOMPOSE_UNICODE
@@@ -209,18 -263,8 +261,18 @@@ extern char *gitbasename(char *)
  #endif
  
  #ifndef NO_OPENSSL
 +#ifdef __APPLE__
 +#define __AVAILABILITY_MACROS_USES_AVAILABILITY 0
 +#include <AvailabilityMacros.h>
 +#undef DEPRECATED_ATTRIBUTE
 +#define DEPRECATED_ATTRIBUTE
 +#undef __AVAILABILITY_MACROS_USES_AVAILABILITY
 +#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
@@@ -482,40 -526,6 +534,40 @@@ extern int git_munmap(void *start, size
  #define on_disk_bytes(st) ((st).st_blocks * 512)
  #endif
  
 +#ifdef NEEDS_MODE_TRANSLATION
 +#undef S_IFMT
 +#undef S_IFREG
 +#undef S_IFDIR
 +#undef S_IFLNK
 +#undef S_IFBLK
 +#undef S_IFCHR
 +#undef S_IFIFO
 +#undef S_IFSOCK
 +#define S_IFMT   0170000
 +#define S_IFREG  0100000
 +#define S_IFDIR  0040000
 +#define S_IFLNK  0120000
 +#define S_IFBLK  0060000
 +#define S_IFCHR  0020000
 +#define S_IFIFO  0010000
 +#define S_IFSOCK 0140000
 +#ifdef stat
 +#undef stat
 +#endif
 +#define stat(path, buf) git_stat(path, buf)
 +extern int git_stat(const char *, struct stat *);
 +#ifdef fstat
 +#undef fstat
 +#endif
 +#define fstat(fd, buf) git_fstat(fd, buf)
 +extern int git_fstat(int, struct stat *);
 +#ifdef lstat
 +#undef lstat
 +#endif
 +#define lstat(path, buf) git_lstat(path, buf)
 +extern int git_lstat(const char *, struct stat *);
 +#endif
 +
  #define DEFAULT_PACKED_GIT_LIMIT \
        ((1024L * 1024L) * (sizeof(void*) >= 8 ? 8192 : 256))
  
@@@ -678,11 -688,6 +730,11 @@@ extern char *xgetcwd(void)
  
  #define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), (alloc) * sizeof(*(x)))
  
 +static inline char *xstrdup_or_null(const char *str)
 +{
 +      return str ? xstrdup(str) : NULL;
 +}
 +
  static inline size_t xsize_t(off_t len)
  {
        if (len > (size_t) len)
  }
  
  /* in ctype.c, for kwset users */
 -extern const char tolower_trans_tbl[256];
 +extern const unsigned char tolower_trans_tbl[256];
  
  /* Sane ctype - no locale, and works with signed chars */
  #undef isascii
@@@ -875,18 -880,4 +927,18 @@@ struct tm *git_gmtime_r(const time_t *
  #define gmtime_r git_gmtime_r
  #endif
  
 +#if !defined(USE_PARENS_AROUND_GETTEXT_N) && defined(__GNUC__)
 +#define USE_PARENS_AROUND_GETTEXT_N 1
 +#endif
 +
 +#ifndef SHELL_PATH
 +# define SHELL_PATH "/bin/sh"
 +#endif
 +
 +#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
 +#define flockfile(fh)
 +#define funlockfile(fh)
 +#define getc_unlocked(fh) getc(fh)
 +#endif
 +
  #endif