Merge branch 'jk/tighten-alloc'
Update various codepaths to avoid manually-counted malloc(). * jk/tighten-alloc: (22 commits) ewah: convert to REALLOC_ARRAY, etc convert ewah/bitmap code to use xmalloc diff_populate_gitlink: use a strbuf transport_anonymize_url: use xstrfmt git-compat-util: drop mempcpy compat code sequencer: simplify memory allocation of get_message test-path-utils: fix normalize_path_copy output buffer size fetch-pack: simplify add_sought_entry fast-import: simplify allocation in start_packfile write_untracked_extension: use FLEX_ALLOC helper prepare_{git,shell}_cmd: use argv_array use st_add and st_mult for allocation size computation convert trivial cases to FLEX_ARRAY macros use xmallocz to avoid size arithmetic convert trivial cases to ALLOC_ARRAY convert manual allocations to argv_array argv-array: add detach function add helpers for allocating flex-array structs harden REALLOC_ARRAY and xcalloc against size_t overflow tree-diff: catch integer overflow in combine_diff_path allocation ...
This commit is contained in:
@ -96,6 +96,14 @@
|
||||
#define unsigned_add_overflows(a, b) \
|
||||
((b) > maximum_unsigned_value_of_type(a) - (a))
|
||||
|
||||
/*
|
||||
* Returns true if the multiplication of "a" and "b" will
|
||||
* overflow. The types of "a" and "b" must match and must be unsigned.
|
||||
* Note that this macro evaluates "a" twice!
|
||||
*/
|
||||
#define unsigned_mult_overflows(a, b) \
|
||||
((a) && (b) > maximum_unsigned_value_of_type(a) / (a))
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define TYPEOF(x) (__typeof__(x))
|
||||
#else
|
||||
@ -669,7 +677,6 @@ extern int git_vsnprintf(char *str, size_t maxsize,
|
||||
#ifdef __GLIBC_PREREQ
|
||||
#if __GLIBC_PREREQ(2, 1)
|
||||
#define HAVE_STRCHRNUL
|
||||
#define HAVE_MEMPCPY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -683,14 +690,6 @@ static inline char *gitstrchrnul(const char *s, int c)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MEMPCPY
|
||||
#define mempcpy gitmempcpy
|
||||
static inline void *gitmempcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
return (char *)memcpy(dest, src, n) + n;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NO_INET_PTON
|
||||
int inet_pton(int af, const char *src, void *dst);
|
||||
#endif
|
||||
@ -709,6 +708,32 @@ extern void release_pack_memory(size_t);
|
||||
typedef void (*try_to_free_t)(size_t);
|
||||
extern try_to_free_t set_try_to_free_routine(try_to_free_t);
|
||||
|
||||
static inline size_t st_add(size_t a, size_t b)
|
||||
{
|
||||
if (unsigned_add_overflows(a, b))
|
||||
die("size_t overflow: %"PRIuMAX" + %"PRIuMAX,
|
||||
(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)))
|
||||
|
||||
static inline size_t st_mult(size_t a, size_t b)
|
||||
{
|
||||
if (unsigned_mult_overflows(a, b))
|
||||
die("size_t overflow: %"PRIuMAX" * %"PRIuMAX,
|
||||
(uintmax_t)a, (uintmax_t)b);
|
||||
return a * b;
|
||||
}
|
||||
|
||||
static inline size_t st_sub(size_t a, size_t b)
|
||||
{
|
||||
if (a < b)
|
||||
die("size_t underflow: %"PRIuMAX" - %"PRIuMAX,
|
||||
(uintmax_t)a, (uintmax_t)b);
|
||||
return a - b;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# define xalloca(size) (alloca(size))
|
||||
@ -741,7 +766,70 @@ extern int odb_pack_keep(char *name, size_t namesz, const unsigned char *sha1);
|
||||
extern char *xgetcwd(void);
|
||||
extern FILE *fopen_for_writing(const char *path);
|
||||
|
||||
#define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), (alloc) * sizeof(*(x)))
|
||||
#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)))
|
||||
|
||||
/*
|
||||
* These functions help you allocate structs with flex arrays, and copy
|
||||
* the data directly into the array. For example, if you had:
|
||||
*
|
||||
* struct foo {
|
||||
* int bar;
|
||||
* char name[FLEX_ARRAY];
|
||||
* };
|
||||
*
|
||||
* you can do:
|
||||
*
|
||||
* struct foo *f;
|
||||
* FLEX_ALLOC_MEM(f, name, src, len);
|
||||
*
|
||||
* to allocate a "foo" with the contents of "src" in the "name" field.
|
||||
* The resulting struct is automatically zero'd, and the flex-array field
|
||||
* is NUL-terminated (whether the incoming src buffer was or not).
|
||||
*
|
||||
* The FLEXPTR_* variants operate on structs that don't use flex-arrays,
|
||||
* but do want to store a pointer to some extra data in the same allocated
|
||||
* block. For example, if you have:
|
||||
*
|
||||
* struct foo {
|
||||
* char *name;
|
||||
* int bar;
|
||||
* };
|
||||
*
|
||||
* you can do:
|
||||
*
|
||||
* struct foo *f;
|
||||
* FLEX_ALLOC_STR(f, name, src);
|
||||
*
|
||||
* and "name" will point to a block of memory after the struct, which will be
|
||||
* freed along with the struct (but the pointer can be repointed anywhere).
|
||||
*
|
||||
* The *_STR variants accept a string parameter rather than a ptr/len
|
||||
* combination.
|
||||
*
|
||||
* Note that these macros will evaluate the first parameter multiple
|
||||
* 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)); \
|
||||
} while (0)
|
||||
#define FLEXPTR_ALLOC_MEM(x, ptrname, buf, len) do { \
|
||||
(x) = xalloc_flex(sizeof(*(x)), sizeof(*(x)), (buf), (len)); \
|
||||
(x)->ptrname = (void *)((x)+1); \
|
||||
} while(0)
|
||||
#define FLEX_ALLOC_STR(x, flexname, str) \
|
||||
FLEX_ALLOC_MEM((x), flexname, (str), strlen(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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user