Merge pull request #11566 from poettering/alloca-assert
add a safety size assert() on most alloca() calls
This commit is contained in:
+32
-17
@@ -10,20 +10,28 @@
|
||||
|
||||
typedef void (*free_func_t)(void *p);
|
||||
|
||||
/* If for some reason more than 4M are allocated on the stack, let's abort immediately. It's better than
|
||||
* proceeding and smashing the stack limits. Note that by default RLIMIT_STACK is 8M on Linux. */
|
||||
#define ALLOCA_MAX (4U*1024U*1024U)
|
||||
|
||||
#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n)))
|
||||
|
||||
#define new0(t, n) ((t*) calloc((n) ?: 1, sizeof(t)))
|
||||
|
||||
#define newa(t, n) \
|
||||
({ \
|
||||
assert(!size_multiply_overflow(sizeof(t), n)); \
|
||||
(t*) alloca(sizeof(t)*(n)); \
|
||||
#define newa(t, n) \
|
||||
({ \
|
||||
size_t _n_ = n; \
|
||||
assert(!size_multiply_overflow(sizeof(t), _n_)); \
|
||||
assert(sizeof(t)*_n_ <= ALLOCA_MAX); \
|
||||
(t*) alloca(sizeof(t)*_n_); \
|
||||
})
|
||||
|
||||
#define newa0(t, n) \
|
||||
({ \
|
||||
assert(!size_multiply_overflow(sizeof(t), n)); \
|
||||
(t*) alloca0(sizeof(t)*(n)); \
|
||||
#define newa0(t, n) \
|
||||
({ \
|
||||
size_t _n_ = n; \
|
||||
assert(!size_multiply_overflow(sizeof(t), _n_)); \
|
||||
assert(sizeof(t)*_n_ <= ALLOCA_MAX); \
|
||||
(t*) alloca0(sizeof(t)*_n_); \
|
||||
})
|
||||
|
||||
#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
|
||||
@@ -51,16 +59,20 @@ void* memdup_suffix0(const void *p, size_t l) _alloc_(2);
|
||||
#define memdupa(p, l) \
|
||||
({ \
|
||||
void *_q_; \
|
||||
_q_ = alloca(l); \
|
||||
memcpy(_q_, p, l); \
|
||||
size_t _l_ = l; \
|
||||
assert(_l_ <= ALLOCA_MAX); \
|
||||
_q_ = alloca(_l_); \
|
||||
memcpy(_q_, p, _l_); \
|
||||
})
|
||||
|
||||
#define memdupa_suffix0(p, l) \
|
||||
({ \
|
||||
void *_q_; \
|
||||
_q_ = alloca(l + 1); \
|
||||
((uint8_t*) _q_)[l] = 0; \
|
||||
memcpy(_q_, p, l); \
|
||||
size_t _l_ = l; \
|
||||
assert(_l_ <= ALLOCA_MAX); \
|
||||
_q_ = alloca(_l_ + 1); \
|
||||
((uint8_t*) _q_)[_l_] = 0; \
|
||||
memcpy(_q_, p, _l_); \
|
||||
})
|
||||
|
||||
static inline void freep(void *p) {
|
||||
@@ -116,6 +128,7 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
|
||||
({ \
|
||||
char *_new_; \
|
||||
size_t _len_ = n; \
|
||||
assert(_len_ <= ALLOCA_MAX); \
|
||||
_new_ = alloca(_len_); \
|
||||
(void *) memset(_new_, 0, _len_); \
|
||||
})
|
||||
@@ -125,16 +138,18 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
|
||||
({ \
|
||||
void *_ptr_; \
|
||||
size_t _mask_ = (align) - 1; \
|
||||
_ptr_ = alloca((size) + _mask_); \
|
||||
size_t _size_ = size; \
|
||||
assert(_size_ <= ALLOCA_MAX); \
|
||||
_ptr_ = alloca(_size_ + _mask_); \
|
||||
(void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
|
||||
})
|
||||
|
||||
#define alloca0_align(size, align) \
|
||||
({ \
|
||||
void *_new_; \
|
||||
size_t _size_ = (size); \
|
||||
_new_ = alloca_align(_size_, (align)); \
|
||||
(void*)memset(_new_, 0, _size_); \
|
||||
size_t _xsize_ = (size); \
|
||||
_new_ = alloca_align(_xsize_, (align)); \
|
||||
(void*)memset(_new_, 0, _xsize_); \
|
||||
})
|
||||
|
||||
/* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to
|
||||
|
||||
@@ -131,7 +131,7 @@ char *prefix_root(const char *root, const char *path);
|
||||
_ret = _path; \
|
||||
else { \
|
||||
_l = strlen(_root) + 1 + strlen(_path) + 1; \
|
||||
_n = alloca(_l); \
|
||||
_n = newa(char, _l); \
|
||||
_p = stpcpy(_n, _root); \
|
||||
while (_p > _n && _p[-1] == '/') \
|
||||
_p--; \
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
if (_pid_ == 0) { \
|
||||
_r_ = ("/proc/self/" field); \
|
||||
} else { \
|
||||
_r_ = alloca(STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
|
||||
sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \
|
||||
_r_ = newa(char, STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
|
||||
sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \
|
||||
} \
|
||||
_r_; \
|
||||
})
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "macro.h"
|
||||
|
||||
/* What is interpreted as whitespace? */
|
||||
@@ -111,7 +112,7 @@ char *strjoin_real(const char *x, ...) _sentinel_;
|
||||
size_t _i_; \
|
||||
for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
|
||||
_len_ += strlen(_appendees_[_i_]); \
|
||||
_p_ = _d_ = alloca(_len_ + 1); \
|
||||
_p_ = _d_ = newa(char, _len_ + 1); \
|
||||
for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
|
||||
_p_ = stpcpy(_p_, _appendees_[_i_]); \
|
||||
*_p_ = 0; \
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <alloca.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "macro.h"
|
||||
|
||||
const char *audit_type_to_string(int type);
|
||||
@@ -15,7 +16,7 @@ int audit_type_from_string(const char *s);
|
||||
const char *_s_; \
|
||||
_s_ = audit_type_to_string(type); \
|
||||
if (!_s_) { \
|
||||
_s_ = alloca(STRLEN("AUDIT") + DECIMAL_STR_MAX(int)); \
|
||||
_s_ = newa(char, STRLEN("AUDIT") + DECIMAL_STR_MAX(int)); \
|
||||
sprintf((char*) _s_, "AUDIT%04i", type); \
|
||||
} \
|
||||
_s_; \
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
const char *_func = (func); \
|
||||
char **_f = &(f); \
|
||||
_fl = strlen(_func) + 1; \
|
||||
*_f = alloca(_fl + 10); \
|
||||
*_f = newa(char, _fl + 10); \
|
||||
memcpy(*_f, "CODE_FUNC=", 10); \
|
||||
memcpy(*_f + 10, _func, _fl); \
|
||||
} while (false)
|
||||
@@ -403,7 +403,7 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve
|
||||
identifier = strempty(identifier);
|
||||
|
||||
l = strlen(identifier);
|
||||
header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
|
||||
header = newa(char, l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
|
||||
|
||||
memcpy(header, identifier, l);
|
||||
header[l++] = '\n';
|
||||
|
||||
@@ -162,7 +162,7 @@ static int map_generic_field(const char *prefix, const char **p, struct iovec **
|
||||
if (e <= *p || e >= *p + 16)
|
||||
return 0;
|
||||
|
||||
c = alloca(strlen(prefix) + (e - *p) + 2);
|
||||
c = newa(char, strlen(prefix) + (e - *p) + 2);
|
||||
|
||||
t = stpcpy(c, prefix);
|
||||
for (f = *p; f < e; f++) {
|
||||
|
||||
@@ -52,7 +52,7 @@ int net_get_unique_predictable_data(sd_device *device, uint64_t *result) {
|
||||
|
||||
l = strlen(name);
|
||||
sz = sizeof(sd_id128_t) + l;
|
||||
v = alloca(sz);
|
||||
v = newa(uint8_t, sz);
|
||||
|
||||
/* fetch some persistent data unique to this machine */
|
||||
r = sd_id128_get_machine((sd_id128_t*) v);
|
||||
|
||||
@@ -1149,7 +1149,7 @@ static int object_manager_serialize_path_and_fallbacks(
|
||||
return 0;
|
||||
|
||||
/* Second, add fallback vtables registered for any of the prefixes */
|
||||
prefix = alloca(strlen(path) + 1);
|
||||
prefix = newa(char, strlen(path) + 1);
|
||||
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
|
||||
r = object_manager_serialize_path(bus, reply, prefix, path, true, error);
|
||||
if (r < 0)
|
||||
@@ -1500,7 +1500,7 @@ static int bus_find_parent_object_manager(sd_bus *bus, struct node **out, const
|
||||
if (!n) {
|
||||
char *prefix;
|
||||
|
||||
prefix = alloca(strlen(path) + 1);
|
||||
prefix = newa(char, strlen(path) + 1);
|
||||
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
|
||||
n = hashmap_get(bus->nodes, prefix);
|
||||
if (n)
|
||||
@@ -2114,7 +2114,7 @@ _public_ int sd_bus_emit_properties_changed_strv(
|
||||
if (bus->nodes_modified)
|
||||
continue;
|
||||
|
||||
prefix = alloca(strlen(path) + 1);
|
||||
prefix = newa(char, strlen(path) + 1);
|
||||
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
|
||||
r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, &found_interface, names);
|
||||
if (r != 0)
|
||||
@@ -2291,7 +2291,7 @@ static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *p
|
||||
if (bus->nodes_modified)
|
||||
return 0;
|
||||
|
||||
prefix = alloca(strlen(path) + 1);
|
||||
prefix = newa(char, strlen(path) + 1);
|
||||
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
|
||||
r = object_added_append_all_prefix(bus, m, s, prefix, path, true);
|
||||
if (r < 0)
|
||||
@@ -2462,7 +2462,7 @@ static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char
|
||||
if (bus->nodes_modified)
|
||||
return 0;
|
||||
|
||||
prefix = alloca(strlen(path) + 1);
|
||||
prefix = newa(char, strlen(path) + 1);
|
||||
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
|
||||
r = object_removed_append_all_prefix(bus, m, s, prefix, path, true);
|
||||
if (r < 0)
|
||||
@@ -2626,7 +2626,7 @@ static int interfaces_added_append_one(
|
||||
if (bus->nodes_modified)
|
||||
return 0;
|
||||
|
||||
prefix = alloca(strlen(path) + 1);
|
||||
prefix = newa(char, strlen(path) + 1);
|
||||
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
|
||||
r = interfaces_added_append_one_prefix(bus, m, prefix, path, interface, true);
|
||||
if (r != 0)
|
||||
|
||||
@@ -981,7 +981,7 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
|
||||
return r;
|
||||
|
||||
n = m->n_iovec * sizeof(struct iovec);
|
||||
iov = alloca(n);
|
||||
iov = newa(struct iovec, n);
|
||||
memcpy_safe(iov, m->iovec, n);
|
||||
|
||||
j = 0;
|
||||
|
||||
@@ -481,7 +481,7 @@ int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
|
||||
|
||||
l = strlen(ifname);
|
||||
sz = sizeof(sd_id128_t) + l;
|
||||
v = alloca(sz);
|
||||
v = newa(uint8_t, sz);
|
||||
|
||||
/* fetch some persistent data unique to the machine */
|
||||
r = sd_id128_get_machine((sd_id128_t*) v);
|
||||
|
||||
@@ -67,7 +67,7 @@ static int generate_mac(
|
||||
if (idx > 0)
|
||||
sz += sizeof(idx);
|
||||
|
||||
v = alloca(sz);
|
||||
v = newa(uint8_t, sz);
|
||||
|
||||
/* fetch some persistent data unique to the host */
|
||||
r = sd_id128_get_machine((sd_id128_t*) v);
|
||||
|
||||
@@ -402,7 +402,7 @@ static int dnssec_ecdsa_verify(
|
||||
if (rrsig->rrsig.signature_size != key_size * 2)
|
||||
return -EINVAL;
|
||||
|
||||
q = alloca(key_size*2 + 1);
|
||||
q = newa(uint8_t, key_size*2 + 1);
|
||||
q[0] = 0x04; /* Prepend 0x04 to indicate an uncompressed key */
|
||||
memcpy(q+1, dnskey->dnskey.key, key_size*2);
|
||||
|
||||
|
||||
@@ -3130,7 +3130,7 @@ static int link_parent(ItemArray *a) {
|
||||
return 0;
|
||||
|
||||
path = a->items[0].path;
|
||||
prefix = alloca(strlen(path) + 1);
|
||||
prefix = newa(char, strlen(path) + 1);
|
||||
PATH_FOREACH_PREFIX(prefix, path) {
|
||||
ItemArray *j;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user