Fix various memory management issues

Consistently handle allocation failures. Some functions are changed to
return bool or int instead of void to allow returning an error.

Also fix a buffer size miscalculation in lua/uloop and use _exit() instead
of exit() on errors after forking.

Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
This commit is contained in:
Matthias Schiffer 2016-06-21 17:19:10 +02:00 committed by Felix Fietkau
parent c2f2c47f3e
commit 1f019ceea1
10 changed files with 83 additions and 23 deletions

View file

@ -227,29 +227,38 @@ blobmsg_open_nested(struct blob_buf *buf, const char *name, bool array)
return (void *)offset; return (void *)offset;
} }
void int
blobmsg_vprintf(struct blob_buf *buf, const char *name, const char *format, va_list arg) blobmsg_vprintf(struct blob_buf *buf, const char *name, const char *format, va_list arg)
{ {
va_list arg2; va_list arg2;
char cbuf; char cbuf;
int len; char *sbuf;
int len, ret;
va_copy(arg2, arg); va_copy(arg2, arg);
len = vsnprintf(&cbuf, sizeof(cbuf), format, arg2); len = vsnprintf(&cbuf, sizeof(cbuf), format, arg2);
va_end(arg2); va_end(arg2);
vsprintf(blobmsg_alloc_string_buffer(buf, name, len + 1), format, arg); sbuf = blobmsg_alloc_string_buffer(buf, name, len + 1);
if (!sbuf)
return -1;
ret = vsprintf(sbuf, format, arg);
blobmsg_add_string_buffer(buf); blobmsg_add_string_buffer(buf);
return ret;
} }
void int
blobmsg_printf(struct blob_buf *buf, const char *name, const char *format, ...) blobmsg_printf(struct blob_buf *buf, const char *name, const char *format, ...)
{ {
va_list ap; va_list ap;
int ret;
va_start(ap, format); va_start(ap, format);
blobmsg_vprintf(buf, name, format, ap); ret = blobmsg_vprintf(buf, name, format, ap);
va_end(ap); va_end(ap);
return ret;
} }
void * void *
@ -278,7 +287,8 @@ blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen)
if (required <= 0) if (required <= 0)
goto out; goto out;
blob_buf_grow(buf, required); if (!blob_buf_grow(buf, required))
return NULL;
attr = blob_next(buf->head); attr = blob_next(buf->head);
out: out:

View file

@ -224,8 +224,8 @@ void *blobmsg_alloc_string_buffer(struct blob_buf *buf, const char *name, unsign
void *blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen); void *blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen);
void blobmsg_add_string_buffer(struct blob_buf *buf); void blobmsg_add_string_buffer(struct blob_buf *buf);
void blobmsg_vprintf(struct blob_buf *buf, const char *name, const char *format, va_list arg); int blobmsg_vprintf(struct blob_buf *buf, const char *name, const char *format, va_list arg);
void blobmsg_printf(struct blob_buf *buf, const char *name, const char *format, ...) int blobmsg_printf(struct blob_buf *buf, const char *name, const char *format, ...)
__attribute__((format(printf, 3, 4))); __attribute__((format(printf, 3, 4)));

View file

@ -119,15 +119,22 @@ struct strbuf {
static bool blobmsg_puts(struct strbuf *s, const char *c, int len) static bool blobmsg_puts(struct strbuf *s, const char *c, int len)
{ {
size_t new_len;
char *new_buf;
if (len <= 0) if (len <= 0)
return true; return true;
if (s->pos + len >= s->len) { if (s->pos + len >= s->len) {
s->len += 16 + len; new_len = s->len + 16 + len;
s->buf = realloc(s->buf, s->len); new_buf = realloc(s->buf, new_len);
if (!s->buf) if (!new_buf)
return false; return false;
s->len = new_len;
s->buf = new_buf;
} }
memcpy(s->buf + s->pos, c, len); memcpy(s->buf + s->pos, c, len);
s->pos += len; s->pos += len;
return true; return true;
@ -290,14 +297,18 @@ char *blobmsg_format_json_with_cb(struct blob_attr *attr, bool list, blobmsg_jso
{ {
struct strbuf s; struct strbuf s;
bool array; bool array;
char *ret;
s.len = blob_len(attr); s.len = blob_len(attr);
s.buf = malloc(s.len);
s.pos = 0; s.pos = 0;
s.custom_format = cb; s.custom_format = cb;
s.priv = priv; s.priv = priv;
s.indent = false; s.indent = false;
s.buf = malloc(s.len);
if (!s.buf)
return NULL;
if (indent >= 0) { if (indent >= 0) {
s.indent = true; s.indent = true;
s.indent_level = indent; s.indent_level = indent;
@ -316,8 +327,13 @@ char *blobmsg_format_json_with_cb(struct blob_attr *attr, bool list, blobmsg_jso
return NULL; return NULL;
} }
s.buf = realloc(s.buf, s.pos + 1); ret = realloc(s.buf, s.pos + 1);
s.buf[s.pos] = 0; if (!ret) {
free(s.buf);
return s.buf; return NULL;
}
ret[s.pos] = 0;
return ret;
} }

4
jshn.c
View file

@ -338,6 +338,10 @@ int main(int argc, char **argv)
for (i = 0; environ[i]; i++); for (i = 0; environ[i]; i++);
vars = calloc(i, sizeof(*vars)); vars = calloc(i, sizeof(*vars));
if (!vars) {
fprintf(stderr, "%m\n");
return -1;
}
for (i = 0; environ[i]; i++) { for (i = 0; environ[i]; i++) {
char *c; char *c;

View file

@ -45,6 +45,9 @@ json_script_file_from_blobmsg(const char *name, void *data, int len)
name_len = strlen(name) + 1; name_len = strlen(name) + 1;
f = calloc_a(sizeof(*f) + len, &new_name, name_len); f = calloc_a(sizeof(*f) + len, &new_name, name_len);
if (!f)
return NULL;
memcpy(f->data, data, len); memcpy(f->data, data, len);
if (name) if (name)
f->avl.key = strcpy(new_name, name); f->avl.key = strcpy(new_name, name);
@ -426,12 +429,15 @@ static int eval_string(struct json_call *call, struct blob_buf *buf, const char
char c = '%'; char c = '%';
dest = blobmsg_alloc_string_buffer(buf, name, 1); dest = blobmsg_alloc_string_buffer(buf, name, 1);
if (!dest)
return -1;
next = alloca(strlen(pattern) + 1); next = alloca(strlen(pattern) + 1);
strcpy(next, pattern); strcpy(next, pattern);
for (str = next; str; str = next) { for (str = next; str; str = next) {
const char *cur; const char *cur;
char *end; char *end, *new_buf;
int cur_len = 0; int cur_len = 0;
bool cur_var = var; bool cur_var = var;
@ -464,7 +470,14 @@ static int eval_string(struct json_call *call, struct blob_buf *buf, const char
cur_len = end - str; cur_len = end - str;
} }
dest = blobmsg_realloc_string_buffer(buf, len + cur_len + 1); new_buf = blobmsg_realloc_string_buffer(buf, len + cur_len + 1);
if (!new_buf) {
/* Make eval_string return -1 */
var = true;
break;
}
dest = new_buf;
memcpy(dest + len, cur, cur_len); memcpy(dest + len, cur, cur_len);
len += cur_len; len += cur_len;
} }

View file

@ -71,20 +71,25 @@ bool kvlist_delete(struct kvlist *kv, const char *name)
return !!node; return !!node;
} }
void kvlist_set(struct kvlist *kv, const char *name, const void *data) bool kvlist_set(struct kvlist *kv, const char *name, const void *data)
{ {
struct kvlist_node *node; struct kvlist_node *node;
char *name_buf; char *name_buf;
int len = kv->get_len(kv, data); int len = kv->get_len(kv, data);
kvlist_delete(kv, name);
node = calloc_a(sizeof(struct kvlist_node) + len, node = calloc_a(sizeof(struct kvlist_node) + len,
&name_buf, strlen(name) + 1); &name_buf, strlen(name) + 1);
if (!node)
return false;
kvlist_delete(kv, name);
memcpy(node->data, data, len); memcpy(node->data, data, len);
node->avl.key = strcpy(name_buf, name); node->avl.key = strcpy(name_buf, name);
avl_insert(&kv->avl, &node->avl); avl_insert(&kv->avl, &node->avl);
return true;
} }
void kvlist_free(struct kvlist *kv) void kvlist_free(struct kvlist *kv)

View file

@ -45,7 +45,7 @@ struct kvlist_node {
void kvlist_init(struct kvlist *kv, int (*get_len)(struct kvlist *kv, const void *data)); void kvlist_init(struct kvlist *kv, int (*get_len)(struct kvlist *kv, const void *data));
void kvlist_free(struct kvlist *kv); void kvlist_free(struct kvlist *kv);
void *kvlist_get(struct kvlist *kv, const char *name); void *kvlist_get(struct kvlist *kv, const char *name);
void kvlist_set(struct kvlist *kv, const char *name, const void *data); bool kvlist_set(struct kvlist *kv, const char *name, const void *data);
bool kvlist_delete(struct kvlist *kv, const char *name); bool kvlist_delete(struct kvlist *kv, const char *name);
int kvlist_strlen(struct kvlist *kv, const void *data); int kvlist_strlen(struct kvlist *kv, const void *data);

View file

@ -325,9 +325,12 @@ static int ul_process(lua_State *L)
int argn = lua_objlen(L, -3); int argn = lua_objlen(L, -3);
int envn = lua_objlen(L, -2); int envn = lua_objlen(L, -2);
char** argp = malloc(sizeof(char*) * (argn + 2)); char** argp = malloc(sizeof(char*) * (argn + 2));
char** envp = malloc(sizeof(char*) * envn + 1); char** envp = malloc(sizeof(char*) * (envn + 1));
int i = 1; int i = 1;
if (!argp || !envp)
_exit(-1);
argp[0] = (char*) lua_tostring(L, -4); argp[0] = (char*) lua_tostring(L, -4);
for (i = 1; i <= argn; i++) { for (i = 1; i <= argn; i++) {
lua_rawgeti(L, -3, i); lua_rawgeti(L, -3, i);
@ -344,7 +347,7 @@ static int ul_process(lua_State *L)
envp[i - 1] = NULL; envp[i - 1] = NULL;
execve(*argp, argp, envp); execve(*argp, argp, envp);
exit(-1); _exit(-1);
} }
lua_getglobal(L, "__uloop_cb"); lua_getglobal(L, "__uloop_cb");

View file

@ -65,6 +65,9 @@ static int ustream_alloc_default(struct ustream *s, struct ustream_buf_list *l)
return -1; return -1;
buf = malloc(sizeof(*buf) + l->buffer_len + s->string_data); buf = malloc(sizeof(*buf) + l->buffer_len + s->string_data);
if (!buf)
return -1;
ustream_init_buf(buf, l->buffer_len); ustream_init_buf(buf, l->buffer_len);
ustream_add_buf(l, buf); ustream_add_buf(l, buf);
@ -490,6 +493,8 @@ int ustream_vprintf(struct ustream *s, const char *format, va_list arg)
return ustream_write_buffered(s, buf, maxlen, wr); return ustream_write_buffered(s, buf, maxlen, wr);
} else { } else {
buf = malloc(maxlen + 1); buf = malloc(maxlen + 1);
if (!buf)
return 0;
wr = vsnprintf(buf, maxlen + 1, format, arg); wr = vsnprintf(buf, maxlen + 1, format, arg);
wr = ustream_write(s, buf, wr, false); wr = ustream_write(s, buf, wr, false);
free(buf); free(buf);
@ -517,6 +522,8 @@ int ustream_vprintf(struct ustream *s, const char *format, va_list arg)
return wr; return wr;
buf = malloc(maxlen + 1); buf = malloc(maxlen + 1);
if (!buf)
return wr;
maxlen = vsnprintf(buf, maxlen + 1, format, arg); maxlen = vsnprintf(buf, maxlen + 1, format, arg);
wr = ustream_write_buffered(s, buf + wr, maxlen - wr, wr); wr = ustream_write_buffered(s, buf + wr, maxlen - wr, wr);
free(buf); free(buf);

View file

@ -43,6 +43,8 @@ void *__calloc_a(size_t len, ...)
va_end(ap1); va_end(ap1);
ptr = calloc(1, alloc_len); ptr = calloc(1, alloc_len);
if (!ptr)
return NULL;
alloc_len = 0; alloc_len = 0;
foreach_arg(ap, cur_addr, cur_len, &ret, len) { foreach_arg(ap, cur_addr, cur_len, &ret, len) {
*cur_addr = &ptr[alloc_len]; *cur_addr = &ptr[alloc_len];