alloc-util: add strdupa_safe() + strndupa_safe() and use it everywhere
Let's define two helpers strdupa_safe() + strndupa_safe() which do the same as their non-safe counterparts, except that they abort if called with allocations larger than ALLOCA_MAX. This should ensure that all our alloca() based allocations are subject to this limit. afaics glibc offers three alloca() based APIs: alloca() itself, strndupa() + strdupa(). With this we have now replacements for all of them, that take the limit into account.
This commit is contained in:
@@ -194,3 +194,19 @@ void* greedy_realloc0(void **p, size_t need, size_t size);
|
||||
__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
|
||||
MALLOC_SIZEOF_SAFE(x)/sizeof((x)[0]), \
|
||||
VOID_0))
|
||||
|
||||
|
||||
/* These are like strdupa()/strndupa(), but honour ALLOCA_MAX */
|
||||
#define strdupa_safe(s) \
|
||||
({ \
|
||||
const char *_t = (s); \
|
||||
(char*) memdupa_suffix0(_t, strlen(_t)); \
|
||||
})
|
||||
|
||||
#define strndupa_safe(s, n) \
|
||||
({ \
|
||||
const char *_t = (s); \
|
||||
(char*) memdupa_suffix0(_t, strnlen(_t, (n))); \
|
||||
})
|
||||
|
||||
#include "memory-util.h"
|
||||
|
||||
@@ -1131,7 +1131,7 @@ int cg_path_decode_unit(const char *cgroup, char **unit) {
|
||||
if (n < 3)
|
||||
return -ENXIO;
|
||||
|
||||
c = strndupa(cgroup, n);
|
||||
c = strndupa_safe(cgroup, n);
|
||||
c = cg_unescape(c);
|
||||
|
||||
if (!unit_name_is_valid(c, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
|
||||
|
||||
@@ -394,7 +394,7 @@ int strv_env_replace_consume(char ***l, char *p) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
name = strndupa(p, t - p);
|
||||
name = strndupa_safe(p, t - p);
|
||||
|
||||
STRV_FOREACH(f, *l)
|
||||
if (env_entry_has_name(*f, name)) {
|
||||
@@ -481,7 +481,7 @@ char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) {
|
||||
if (flags & REPLACE_ENV_USE_ENVIRONMENT) {
|
||||
const char *t;
|
||||
|
||||
t = strndupa(name, k);
|
||||
t = strndupa_safe(name, k);
|
||||
return getenv(t);
|
||||
};
|
||||
|
||||
@@ -804,7 +804,7 @@ int putenv_dup(const char *assignment, bool override) {
|
||||
if (!e)
|
||||
return -EINVAL;
|
||||
|
||||
n = strndupa(assignment, e - assignment);
|
||||
n = strndupa_safe(assignment, e - assignment);
|
||||
|
||||
/* This is like putenv(), but uses setenv() so that our memory doesn't become part of environ[]. */
|
||||
if (setenv(n, e + 1, override) < 0)
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ int rmdir_parents(const char *path, const char *stop) {
|
||||
if (!path_is_safe(stop))
|
||||
return -EINVAL;
|
||||
|
||||
p = strdupa(path);
|
||||
p = strdupa_safe(path);
|
||||
|
||||
for (;;) {
|
||||
char *slash = NULL;
|
||||
|
||||
+4
-2
@@ -1073,8 +1073,10 @@ int log_struct_iovec_internal(
|
||||
|
||||
for (size_t i = 0; i < n_input_iovec; i++)
|
||||
if (memory_startswith(input_iovec[i].iov_base, input_iovec[i].iov_len, "MESSAGE=")) {
|
||||
char *m = strndupa(input_iovec[i].iov_base + STRLEN("MESSAGE="),
|
||||
input_iovec[i].iov_len - STRLEN("MESSAGE="));
|
||||
char *m;
|
||||
|
||||
m = strndupa_safe((char*) input_iovec[i].iov_base + STRLEN("MESSAGE="),
|
||||
input_iovec[i].iov_len - STRLEN("MESSAGE="));
|
||||
|
||||
return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, m);
|
||||
}
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, ui
|
||||
assert(*e == '/');
|
||||
|
||||
/* drop the last component */
|
||||
path = strndupa(path, e - path);
|
||||
path = strndupa_safe(path, e - path);
|
||||
r = is_dir(path, true);
|
||||
if (r > 0)
|
||||
return 0;
|
||||
|
||||
@@ -156,7 +156,7 @@ static bool filename_possibly_with_slash_suffix(const char *s) {
|
||||
if (slash[strspn(slash, "/")] != 0) /* Check that the suffix consist only of one or more slashes */
|
||||
return false;
|
||||
|
||||
copied = strndupa(s, slash - s);
|
||||
copied = strndupa_safe(s, slash - s);
|
||||
return filename_is_valid(copied);
|
||||
}
|
||||
|
||||
|
||||
@@ -704,7 +704,7 @@ int parse_dev(const char *s, dev_t *ret) {
|
||||
if (s[n] != ':')
|
||||
return -EINVAL;
|
||||
|
||||
major = strndupa(s, n);
|
||||
major = strndupa_safe(s, n);
|
||||
r = safe_atou(major, &x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -765,7 +765,7 @@ int parse_loadavg_fixed_point(const char *s, loadavg_t *ret) {
|
||||
if (!d)
|
||||
return -EINVAL;
|
||||
|
||||
i_str = strndupa(s, d - s);
|
||||
i_str = strndupa_safe(s, d - s);
|
||||
f_str = d + 1;
|
||||
|
||||
r = safe_atolu_full(i_str, 10, &i);
|
||||
|
||||
@@ -489,7 +489,7 @@ static int get_paths_from_environ(const char *var, char ***paths, bool *append)
|
||||
|
||||
k = endswith(e, ":");
|
||||
if (k) {
|
||||
e = strndupa(e, k - e);
|
||||
e = strndupa_safe(e, k - e);
|
||||
*append = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ static int parse_parts_value_whole(const char *p, const char *symbol) {
|
||||
if (!pc)
|
||||
return -EINVAL;
|
||||
|
||||
n = strndupa(p, pc - p);
|
||||
n = strndupa_safe(p, pc - p);
|
||||
r = safe_atoi(n, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -37,10 +37,10 @@ static int parse_parts_value_with_tenths_place(const char *p, const char *symbol
|
||||
if (dot[1] < '0' || dot[1] > '9')
|
||||
return -EINVAL;
|
||||
q = dot[1] - '0';
|
||||
n = strndupa(p, dot - p);
|
||||
n = strndupa_safe(p, dot - p);
|
||||
} else {
|
||||
q = 0;
|
||||
n = strndupa(p, pc - p);
|
||||
n = strndupa_safe(p, pc - p);
|
||||
}
|
||||
r = safe_atoi(n, &v);
|
||||
if (r < 0)
|
||||
@@ -81,10 +81,10 @@ static int parse_parts_value_with_hundredths_place(const char *p, const char *sy
|
||||
/* We do not support zero or more than two places */
|
||||
return -EINVAL;
|
||||
|
||||
n = strndupa(p, dot - p);
|
||||
n = strndupa_safe(p, dot - p);
|
||||
} else {
|
||||
q = 0;
|
||||
n = strndupa(p, pc - p);
|
||||
n = strndupa_safe(p, pc - p);
|
||||
}
|
||||
r = safe_atoi(n, &v);
|
||||
if (r < 0)
|
||||
|
||||
@@ -135,7 +135,7 @@ int procfs_tasks_get_current(uint64_t *ret) {
|
||||
|
||||
p++;
|
||||
n = strspn(p, DIGITS);
|
||||
nr = strndupa(p, n);
|
||||
nr = strndupa_safe(p, n);
|
||||
|
||||
return safe_atou64(nr, ret);
|
||||
}
|
||||
|
||||
@@ -671,7 +671,7 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
|
||||
goto finish;
|
||||
|
||||
} else if ((k = endswith(t, " ago"))) {
|
||||
t = strndupa(t, k - t);
|
||||
t = strndupa_safe(t, k - t);
|
||||
|
||||
r = parse_sec(t, &minus);
|
||||
if (r < 0)
|
||||
@@ -680,7 +680,7 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
|
||||
goto finish;
|
||||
|
||||
} else if ((k = endswith(t, " left"))) {
|
||||
t = strndupa(t, k - t);
|
||||
t = strndupa_safe(t, k - t);
|
||||
|
||||
r = parse_sec(t, &plus);
|
||||
if (r < 0)
|
||||
@@ -692,7 +692,7 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
|
||||
/* See if the timestamp is suffixed with UTC */
|
||||
utc = endswith_no_case(t, " UTC");
|
||||
if (utc)
|
||||
t = strndupa(t, utc - t);
|
||||
t = strndupa_safe(t, utc - t);
|
||||
else {
|
||||
const char *e = NULL;
|
||||
int j;
|
||||
@@ -723,7 +723,7 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
|
||||
|
||||
if (IN_SET(j, 0, 1)) {
|
||||
/* Found one of the two timezones specified. */
|
||||
t = strndupa(t, e - t - 1);
|
||||
t = strndupa_safe(t, e - t - 1);
|
||||
dst = j;
|
||||
tzn = tzname[j];
|
||||
}
|
||||
@@ -924,7 +924,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
||||
|
||||
/* Cut off the timezone if we don't need it. */
|
||||
if (with_tz)
|
||||
t = strndupa(t, last_space - t);
|
||||
t = strndupa_safe(t, last_space - t);
|
||||
|
||||
shared->return_value = parse_timestamp_impl(t, &shared->usec, with_tz);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user