From 9d9e0c2979f43297b2ebbf84f14f064f3f9ced0e Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Mon, 19 Feb 2024 22:49:09 +0100 Subject: [PATCH] html.c: Avoid half-init objects on html_node_add_attr The previous implementation would leave half-initialised objects if one of the calls to strdup(3) failed. Now, n->attrs is only modified when all previous memory allocations were successful. --- html.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/html.c b/html.c index 5a92d77..0277498 100644 --- a/html.c +++ b/html.c @@ -110,30 +110,41 @@ int html_node_add_attr(struct html_node *const n, const char *const attr, const char *const val) { const size_t el = n->n + 1; - struct html_attribute *const attrs = realloc(n->attrs, - el * sizeof *n->attrs), *a = NULL; + char *const attrdup = strdup(attr), *valdup = NULL; + struct html_attribute *attrs = NULL; - if (!attrs) + if (!attrdup) + { + fprintf(stderr, "%s: strdup(3) attr: %s\n", __func__, strerror(errno)); + goto failure; + } + else if (val && !(valdup = strdup(val))) + { + fprintf(stderr, "%s: strdup(3) val: %s\n", __func__, strerror(errno)); + goto failure; + } + else if (!(attrs = realloc(n->attrs, el * sizeof *attrs))) { fprintf(stderr, "%s: realloc(3): %s\n", __func__, strerror(errno)); return -1; } - a = &attrs[n->n]; - *a = (const struct html_attribute){0}; + struct html_attribute *const a = &attrs[n->n]; - if (!(a->attr = strdup(attr)) - || (val && !(a->value = strdup(val)))) + *a = (const struct html_attribute) { - fprintf(stderr, "%s: strdup(3): %s\n", __func__, strerror(errno)); - free(a->attr); - free(a->value); - return -1; - } + .attr = attrdup, + .value = valdup + }; n->attrs = attrs; n->n = el; return 0; + +failure: + free(attrdup); + free(valdup); + return -1; } void html_node_add_sibling(struct html_node *const n,