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:
parent
d83e8ad1ba
commit
62bdf9f72f
26
handler.c
26
handler.c
|
@ -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
13
html.c
|
@ -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
49
http.c
|
@ -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;
|
||||
|
||||
|
|
24
server.c
24
server.c
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue