Fix memory leak on failed realloc(3)

According to C99 §7.20.3.4:

If memory for the new object cannot be allocated, the old object is not
deallocated and its value is unchanged.

Therefore, a temporary pointer must be used to ensure the original
object can still be deallocated should realloc(3) return a null pointer.
This commit is contained in:
Xavier Del Campo Romero 2023-03-04 02:06:19 +01:00
parent d83e8ad1ba
commit 62bdf9f72f
Signed by: xavi
GPG Key ID: 84FF3612A9BF43F2
4 changed files with 79 additions and 33 deletions

View File

@ -310,27 +310,33 @@ struct handler *handler_alloc(const char *const tmpdir)
int handler_add(struct handler *const h, const char *url,
const enum http_op op, const handler_fn f, void *const user)
{
if (!h || !(h->cfg = realloc(h->cfg, (h->n_cfg + 1) * sizeof *h->cfg)))
const size_t n = h->n_cfg + 1;
struct handler_cfg *const cfgs = realloc(h->cfg, n * sizeof *h->cfg),
*c = NULL;
if (!cfgs)
{
fprintf(stderr, "%s: realloc(3): %s\n", __func__, strerror(errno));
return -1;
}
char *const new = strdup(url);
c = &cfgs[h->n_cfg];
if (!new)
*c = (const struct handler_cfg)
{
fprintf(stderr, "%s: malloc(3): %s\n", __func__, strerror(errno));
return -1;
}
h->cfg[h->n_cfg++] = (const struct handler_cfg)
{
.url = new,
.url = strdup(url),
.op = op,
.f = f,
.user = user
};
if (!c->url)
{
fprintf(stderr, "%s: strdup(3): %s\n", __func__, strerror(errno));
return -1;
}
h->cfg = cfgs;
h->n_cfg = n;
return 0;
}

13
html.c
View File

@ -101,25 +101,30 @@ int html_node_set_value_unescaped(struct html_node *const n,
int html_node_add_attr(struct html_node *const n, const char *const attr,
const char *const val)
{
if (!(n->attrs = realloc(n->attrs, (n->n + 1) * sizeof *n->attrs)))
const size_t el = n->n + 1;
struct html_attribute *const attrs = realloc(n->attrs,
el * sizeof *n->attrs), *a = NULL;
if (!attrs)
{
fprintf(stderr, "%s: realloc(3): %s\n", __func__, strerror(errno));
return -1;
}
struct html_attribute *const a = &n->attrs[n->n++];
a = &attrs[n->n];
*a = (const struct html_attribute){0};
if (!(a->attr = strdup(attr))
|| (val && !(a->value = strdup(val))))
{
fprintf(stderr, "%s: malloc(3): %s\n", __func__, strerror(errno));
fprintf(stderr, "%s: strdup(3): %s\n", __func__, strerror(errno));
free(a->attr);
free(a->value);
return -1;
}
n->attrs = attrs;
n->n = el;
return 0;
}

49
http.c
View File

@ -470,14 +470,17 @@ static int http_write(struct http_ctx *const h, bool *const close)
int http_response_add_header(struct http_response *const r,
const char *const header, const char *const value)
{
if (!(r->headers = realloc(r->headers,
sizeof (r->n_headers + 1) *sizeof *r->headers)))
const size_t n = r->n_headers + 1;
struct http_header *const headers = realloc(r->headers,
n * sizeof *r->headers), *h = NULL;
if (!headers)
{
fprintf(stderr, "%s: realloc(3): %s\n", __func__, strerror(errno));
return -1;
}
struct http_header *const h = &r->headers[r->n_headers++];
h = &headers[r->n_headers];
*h = (const struct http_header)
{
@ -487,13 +490,14 @@ int http_response_add_header(struct http_response *const r,
if (!h->header || !h->value)
{
fprintf(stderr, "%s: malloc(3): %s\n", __func__, strerror(errno));
fprintf(stderr, "%s: strdup(3): %s\n", __func__, strerror(errno));
free(h->header);
free(h->value);
free(h);
return -1;
}
r->headers = headers;
r->n_headers = n;
return 0;
}
@ -984,16 +988,21 @@ static int set_content_disposition(struct http_ctx *const h,
__func__, (int)(sep - c), c);
return 1;
}
else if (!(m->forms = realloc(m->forms,
(m->nforms + 1) * sizeof *m->forms)))
const size_t n = m->nforms + 1;
struct form *const forms = realloc(m->forms, n * sizeof *m->forms);
if (!forms)
{
fprintf(stderr, "%s: realloc(3): %s\n", __func__, strerror(errno));
return -1;
}
struct form *const f = &m->forms[m->nforms++];
struct form *const f = &forms[m->nforms];
*f = (const struct form){0};
m->nforms = n;
m->forms = forms;
return cd_fields(h, f, sep);
}
@ -1193,13 +1202,17 @@ static int apply_from_file(struct http_ctx *const h, struct form *const f)
m->fd = -1;
if (!(m->files = realloc(m->files, (m->nfiles + 1) * sizeof *m->files)))
const size_t n = m->nfiles + 1;
struct http_post_file *const files = realloc(m->files,
n * sizeof *m->files);
if (!files)
{
fprintf(stderr, "%s: realloc(3): %s\n", __func__, strerror(errno));
return -1;
}
struct http_post_file *const pf = &m->files[m->nfiles++];
struct http_post_file *const pf = &files[m->nfiles];
*pf = (const struct http_post_file)
{
@ -1207,6 +1220,8 @@ static int apply_from_file(struct http_ctx *const h, struct form *const f)
.filename = f->filename
};
m->files = files;
m->nfiles = n;
return 0;
}
@ -1575,13 +1590,18 @@ char *http_decode_url(const char *url)
while (*url)
{
if (!(ret = realloc(ret, n + 1)))
char *const r = realloc(ret, n + 1);
if (!r)
{
fprintf(stderr, "%s: realloc(3) loop: %s\n",
__func__, strerror(errno));
goto failure;
}
else if (*url != '%')
ret = r;
if (*url != '%')
ret[n++] = *url++;
else if (*(url + 1) && *(url + 2))
{
@ -1597,12 +1617,15 @@ char *http_decode_url(const char *url)
}
}
if (!(ret = realloc(ret, n + 1)))
char *const r = realloc(ret, n + 1);
if (!r)
{
fprintf(stderr, "%s: realloc(3) end: %s\n", __func__, strerror(errno));
goto failure;
}
ret = r;
ret[n] = '\0';
return ret;

View File

@ -58,12 +58,17 @@ int server_client_close(struct server *const s, struct server_client *const c)
{
memcpy(ref, ref + 1, s->n - i);
if (!(s->c = realloc(s->c, (s->n - 1) * sizeof *s->c)))
const size_t n = s->n - 1;
struct server_client *const c = realloc(s->c, n * sizeof *s->c);
if (!c)
{
fprintf(stderr, "%s: realloc(3): %s\n",
__func__, strerror(errno));
return -1;
}
s->c = c;
}
else
{
@ -127,19 +132,26 @@ static struct server_client *alloc_client(struct server *const s)
__func__, strerror(errno));
return NULL;
}
else if (!(s->c = realloc(s->c, (s->n + 1) * sizeof *s->c)))
const size_t n = s->n + 1;
struct server_client *const clients = realloc(s->c, n * sizeof *s->c);
if (!clients)
{
fprintf(stderr, "%s: realloc(3): %s\n",
__func__, strerror(errno));
fprintf(stderr, "%s: realloc(3): %s\n", __func__, strerror(errno));
return NULL;
}
s->c[s->n] = (const struct server_client)
struct server_client *const c = &clients[s->n];
*c = (const struct server_client)
{
.fd = fd
};
return &s->c[s->n++];
s->c = clients;
s->n = n;
return c;
}
void server_client_write_pending(struct server_client *const c,