diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-03-04 02:06:19 +0100 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-07-20 23:52:51 +0200 |
| commit | 67ffb772b7488b84e37e6880290820fc54434b33 (patch) | |
| tree | 574f95ad5834282261846daede1f653b1d1d0666 | |
| parent | 37fd5c92aebd87af14a1f73f8e567b8b74f6bd36 (diff) | |
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.
| -rw-r--r-- | handler.c | 26 | ||||
| -rw-r--r-- | html.c | 13 | ||||
| -rw-r--r-- | http.c | 49 | ||||
| -rw-r--r-- | server.c | 24 |
4 files changed, 79 insertions, 33 deletions
@@ -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); - - if (!new) - { - fprintf(stderr, "%s: malloc(3): %s\n", __func__, strerror(errno)); - return -1; - } + c = &cfgs[h->n_cfg]; - h->cfg[h->n_cfg++] = (const struct handler_cfg) + *c = (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; } @@ -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; } @@ -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; @@ -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, |
