Skip to content

Commit 7d317df

Browse files
committed
node: fix reference counting in normalize
With thanks to Shaunak Mirani for reporting the problem.
1 parent 436d143 commit 7d317df

File tree

5 files changed

+172
-2
lines changed

5 files changed

+172
-2
lines changed

src/core/node.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,7 @@ dom_exception _dom_node_normalize(dom_node_internal *node)
11801180
return err;
11811181

11821182
_dom_node_detach(n);
1183-
dom_node_unref(n);
1183+
dom_node_try_destroy(n);
11841184
n = p->next;
11851185
continue;
11861186
}

test/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,13 @@ $(DIR)INDEX: test/Makefile
5454
ifeq ($(WANT_XML_TEST),yes)
5555
$(foreach XMLTEST,$(sort $(ALL_XML_TESTS)),$(call write_index,$(XMLTEST)))
5656
endif
57-
$(Q)$(ECHO) "normalize Normalize nodes normalize" > $@
57+
$(Q)$(ECHO) "normalize Normalize nodes normalize" >> $@
58+
$(Q)$(ECHO) "normalize2 Normalize nodes normalize2" >> $@
5859

5960
TEST_PREREQS := $(TEST_PREREQS) $(DIR)INDEX
6061

6162
DIR_TEST_ITEMS := $(DIR_TEST_ITEMS) normalize:normalize.c;$(testutils_files)
63+
DIR_TEST_ITEMS := $(DIR_TEST_ITEMS) normalize2:normalize2.c;$(testutils_files)
6264
# Include the level 1 core tests
6365
$(eval $(call do_xml_suite,level1/core,dom1-interfaces.xml))
6466
# Include level 1 html tests

test/data/normalize2/INDEX

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Index file for generic CSS content
2+
#
3+
# Test Description
4+
refcnt.html Reference counting

test/data/normalize2/refcnt.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<html>
2+
<head></head>
3+
<body>
4+
<p>foo
5+
</body>
6+
</html>

test/normalize2.c

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
* This file is part of libdom test suite.
3+
* Licensed under the MIT License,
4+
* http://www.opensource.org/licenses/mit-license.php
5+
* Copyright 2024 Daniel Silverstone <dsilvers@netsurf-browser.org>
6+
*/
7+
8+
#include <stdio.h>
9+
#include <stdbool.h>
10+
11+
#include "testutils/domts.h"
12+
13+
static dom_exception
14+
get_node(dom_document *doc, dom_string *tag, dom_node **out)
15+
{
16+
dom_nodelist *nodes;
17+
dom_exception err;
18+
dom_node *docele;
19+
dom_node *ret;
20+
21+
err = dom_document_get_document_element(doc, &docele);
22+
if (err != DOM_NO_ERR) {
23+
printf("Could not get document node\n");
24+
return err;
25+
}
26+
err = dom_element_get_elements_by_tag_name(docele, tag, &nodes);
27+
dom_node_unref(docele);
28+
if (err != DOM_NO_ERR) {
29+
printf("Could not enumerate elements for %*s\n",
30+
dom_string_length(tag),
31+
dom_string_data(tag));
32+
return err;
33+
}
34+
35+
err = dom_nodelist_item(nodes, 0, &ret);
36+
dom_nodelist_unref(nodes);
37+
if (err != DOM_NO_ERR) {
38+
printf("Could not retrieve element[0] for %*s\n",
39+
dom_string_length(tag),
40+
dom_string_data(tag));
41+
return err;
42+
}
43+
44+
*out = ret;
45+
46+
return DOM_NO_ERR;
47+
}
48+
49+
static bool test_normalize(const char *fname)
50+
{
51+
bool outcome = true;
52+
dom_document *doc = NULL;
53+
dom_string *domBODY = NULL;
54+
dom_node *body = NULL, *p = NULL, *text = NULL;
55+
dom_node_type type;
56+
dom_exception err = DOM_NO_ERR;
57+
58+
printf("Loading: %s\n", fname);
59+
doc = load_html(fname, false);
60+
if (doc == NULL) {
61+
printf("Failed to load file\n");
62+
outcome = false;
63+
goto cleanup;
64+
}
65+
66+
/* We have an HTML document so we normalise the body */
67+
68+
err = dom_string_create((uint8_t *)"BODY", 4, &domBODY);
69+
if (err != DOM_NO_ERR) {
70+
printf("Failed to create BODY string\n");
71+
outcome = false;
72+
goto cleanup;
73+
}
74+
75+
err = get_node(doc, domBODY, &body);
76+
if (err != DOM_NO_ERR) {
77+
outcome = false;
78+
goto cleanup;
79+
}
80+
81+
err = dom_node_get_first_child(body, &p);
82+
if (err != DOM_NO_ERR) {
83+
outcome = false;
84+
goto cleanup;
85+
}
86+
87+
err = dom_node_get_node_type(p, &type);
88+
if (err != DOM_NO_ERR) {
89+
outcome = false;
90+
goto cleanup;
91+
}
92+
93+
while (p != NULL && type != DOM_ELEMENT_NODE) {
94+
dom_node *next = NULL;
95+
err = dom_node_get_next_sibling(p, &next);
96+
if (err != DOM_NO_ERR) {
97+
outcome = false;
98+
goto cleanup;
99+
}
100+
dom_node_unref(p);
101+
p = next;
102+
err = dom_node_get_node_type(p, &type);
103+
if (err != DOM_NO_ERR) {
104+
outcome = false;
105+
goto cleanup;
106+
}
107+
}
108+
109+
err = dom_node_get_last_child(p, &text);
110+
if (err != DOM_NO_ERR) {
111+
outcome = false;
112+
goto cleanup;
113+
}
114+
115+
printf("Normalizing body, please wait...\n");
116+
err = dom_node_normalize(body);
117+
if (err != DOM_NO_ERR) {
118+
printf("Failed to normalize body\n");
119+
outcome = false;
120+
goto cleanup;
121+
}
122+
123+
err = dom_node_get_node_type(text, &type);
124+
if (err != DOM_NO_ERR) {
125+
outcome = false;
126+
goto cleanup;
127+
}
128+
129+
printf("All done\n");
130+
131+
cleanup:
132+
if (err != DOM_NO_ERR) {
133+
printf("DOM Exception: %d\n", err);
134+
}
135+
dom_node_unref(text);
136+
dom_node_unref(p);
137+
dom_node_unref(body);
138+
dom_string_unref(domBODY);
139+
dom_node_unref(doc);
140+
return outcome;
141+
}
142+
143+
int main(int argc, char **argv)
144+
{
145+
if (argc != 2) {
146+
fprintf(stderr, "usage: %s inputfile", argv[0]);
147+
return 1;
148+
}
149+
150+
/* This test simply loads the HTML and normalises the top node */
151+
if (!test_normalize(argv[1])) {
152+
printf("\nFAILED\n");
153+
return 1;
154+
}
155+
156+
printf("\nPASS\n");
157+
return 0;
158+
}

0 commit comments

Comments
 (0)