diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2024-02-19 22:49:09 +0100 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2024-02-19 22:49:09 +0100 |
| commit | 9d9e0c2979f43297b2ebbf84f14f064f3f9ced0e (patch) | |
| tree | 95f89b3c89c1e8bfa8cf75068b06d8f89b6c099f | |
| parent | 6ceae16a20175edb77fb2ffab0d3d6648d011221 (diff) | |
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.
| -rw-r--r-- | html.c | 35 |
1 files changed, 23 insertions, 12 deletions
@@ -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, |
