|
24 | 24 | #include "gcc-macro.h"
|
25 | 25 | #include "log.h"
|
26 | 26 |
|
27 |
| -#define new(t, n) ((t*) malloc((n) * sizeof(t))) |
28 |
| -#define new0(t, n) ((t*) calloc((n), sizeof(t))) |
| 27 | +/* If for some reason more than 4M are allocated on the stack, let's abort immediately. It's better than |
| 28 | + * proceeding and smashing the stack limits. Note that by default RLIMIT_STACK is 8M on Linux. */ |
| 29 | +#define ALLOCA_MAX (4U*1024U*1024U) |
29 | 30 |
|
30 |
| -#define newa(t, n) ((t*) alloca((n) * sizeof(t))) |
| 31 | +#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n))) |
| 32 | +#define new0(t, n) ((t*) calloc((n) ?: 1, sizeof(t))) |
| 33 | + |
| 34 | +#define newa(t, n) \ |
| 35 | + ({ \ |
| 36 | + size_t _n_ = n; \ |
| 37 | + assert(!size_multiply_overflow(sizeof(t), _n_)); \ |
| 38 | + assert(sizeof(t)*_n_ <= ALLOCA_MAX); \ |
| 39 | + (t*) alloca(sizeof(t)*_n_); \ |
| 40 | + }) |
| 41 | + |
| 42 | +#define newa0(t, n) \ |
| 43 | + ({ \ |
| 44 | + size_t _n_ = n; \ |
| 45 | + assert(!size_multiply_overflow(sizeof(t), _n_)); \ |
| 46 | + assert(sizeof(t)*_n_ <= ALLOCA_MAX); \ |
| 47 | + (t*) alloca0(sizeof(t)*_n_); \ |
| 48 | + }) |
| 49 | + |
| 50 | +#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n))) |
| 51 | + |
| 52 | +#define malloc0(n) (calloc(1, (n))) |
31 | 53 |
|
32 | 54 | #define XCONCATENATE(x, y) x ## y
|
33 | 55 | #define CONCATENATE(x, y) XCONCATENATE(x, y)
|
|
63 | 85 | ((_A) > (_B)) ? (_A) : (_B), \
|
64 | 86 | (void)0))
|
65 | 87 |
|
66 |
| - |
67 |
| - |
68 | 88 | int loop_write(int fd, const void *p, size_t l);
|
69 | 89 | int loop_write_block(int fd, const void *p, size_t l);
|
70 | 90 | ssize_t loop_read(int fd, void *p, size_t l);
|
@@ -330,22 +350,39 @@ char *strv_find(char **l, const char *name) _pure_;
|
330 | 350 | #define strv_contains(l, s) (!!strv_find((l), (s)))
|
331 | 351 |
|
332 | 352 | static inline bool size_multiply_overflow(size_t size, size_t need) {
|
333 |
| - return need != 0 && size > (SIZE_MAX / need); |
| 353 | + return _unlikely_(need != 0 && size > (SIZE_MAX / need)); |
334 | 354 | }
|
335 | 355 |
|
336 | 356 | _malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) {
|
337 |
| - if (_unlikely_(size_multiply_overflow(size, need))) |
| 357 | + if (size_multiply_overflow(size, need)) |
338 | 358 | return NULL;
|
339 | 359 |
|
340 |
| - return malloc(size * need); |
| 360 | + return malloc(size * need ?: 1); |
341 | 361 | }
|
342 | 362 |
|
343 |
| -_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t size, size_t need) { |
344 |
| - if (_unlikely_(size_multiply_overflow(size, need))) |
| 363 | +#if !HAVE_REALLOCARRAY |
| 364 | +_alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) { |
| 365 | + if (size_multiply_overflow(size, need)) |
345 | 366 | return NULL;
|
346 | 367 |
|
347 |
| - return realloc(p, size * need); |
| 368 | + return realloc(p, size * need ?: 1); |
348 | 369 | }
|
| 370 | +#endif |
| 371 | + |
| 372 | +_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) { |
| 373 | + if (size_multiply_overflow(size, need)) |
| 374 | + return NULL; |
| 375 | + |
| 376 | + return memdup(p, size * need); |
| 377 | +} |
| 378 | + |
| 379 | +#define free_and_replace(a, b) \ |
| 380 | + ({ \ |
| 381 | + free(a); \ |
| 382 | + (a) = (b); \ |
| 383 | + (b) = NULL; \ |
| 384 | + 0; \ |
| 385 | + }) |
349 | 386 |
|
350 | 387 | #define STRV_FOREACH(s, l) \
|
351 | 388 | for ((s) = (l); (s) && *(s); (s)++)
|
|
0 commit comments