]>
Commit | Line | Data |
---|---|---|
1 | #include <assert.h> | |
2 | #include <check.h> | |
3 | #include <stdlib.h> | |
4 | #include <stdio.h> | |
5 | #include <string.h> | |
6 | ||
7 | #include "expat.h" | |
8 | #include "chardata.h" | |
9 | ||
10 | ||
11 | static XML_Parser parser; | |
12 | ||
13 | ||
14 | static void | |
15 | basic_setup(void) | |
16 | { | |
17 | parser = XML_ParserCreate(NULL); | |
18 | if (parser == NULL) | |
19 | fail("Parser not created."); | |
20 | } | |
21 | ||
22 | static void | |
23 | basic_teardown(void) | |
24 | { | |
25 | if (parser != NULL) | |
26 | XML_ParserFree(parser); | |
27 | } | |
28 | ||
29 | /* Generate a failure using the parser state to create an error message; | |
30 | this should be used when the parser reports an error we weren't | |
31 | expecting. | |
32 | */ | |
33 | static void | |
34 | _xml_failure(XML_Parser parser, const char *file, int line) | |
35 | { | |
36 | char buffer[1024]; | |
37 | sprintf(buffer, | |
38 | "\n %s (line %d, offset %d)\n reported from %s, line %d", | |
39 | XML_ErrorString(XML_GetErrorCode(parser)), | |
40 | XML_GetCurrentLineNumber(parser), | |
41 | XML_GetCurrentColumnNumber(parser), | |
42 | file, line); | |
43 | _fail_unless(0, file, line, buffer); | |
44 | } | |
45 | ||
46 | #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__) | |
47 | ||
48 | static void | |
49 | _expect_failure(char *text, enum XML_Error errorCode, char *errorMessage, | |
50 | char *file, int lineno) | |
51 | { | |
52 | if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_OK) | |
53 | /* Hackish use of _fail_unless() macro, but let's us report | |
54 | the right filename and line number. */ | |
55 | _fail_unless(0, file, lineno, errorMessage); | |
56 | if (XML_GetErrorCode(parser) != errorCode) | |
57 | _xml_failure(parser, file, lineno); | |
58 | } | |
59 | ||
60 | #define expect_failure(text, errorCode, errorMessage) \ | |
61 | _expect_failure((text), (errorCode), (errorMessage), \ | |
62 | __FILE__, __LINE__) | |
63 | ||
64 | /* Dummy handlers for when we need to set a handler to tickle a bug, | |
65 | but it doesn't need to do anything. | |
66 | */ | |
67 | ||
68 | static void | |
69 | dummy_start_doctype_handler(void *userData, | |
70 | const XML_Char *doctypeName, | |
71 | const XML_Char *sysid, | |
72 | const XML_Char *pubid, | |
73 | int has_internal_subset) | |
74 | {} | |
75 | ||
76 | static void | |
77 | dummy_end_doctype_handler(void *userData) | |
78 | {} | |
79 | ||
80 | static void | |
81 | dummy_entity_decl_handler(void *userData, | |
82 | const XML_Char *entityName, | |
83 | int is_parameter_entity, | |
84 | const XML_Char *value, | |
85 | int value_length, | |
86 | const XML_Char *base, | |
87 | const XML_Char *systemId, | |
88 | const XML_Char *publicId, | |
89 | const XML_Char *notationName) | |
90 | {} | |
91 | ||
92 | static void | |
93 | dummy_notation_decl_handler(void *userData, | |
94 | const XML_Char *notationName, | |
95 | const XML_Char *base, | |
96 | const XML_Char *systemId, | |
97 | const XML_Char *publicId) | |
98 | {} | |
99 | ||
100 | static void | |
101 | dummy_element_decl_handler(void *userData, | |
102 | const XML_Char *name, | |
103 | XML_Content *model) | |
104 | {} | |
105 | ||
106 | static void | |
107 | dummy_attlist_decl_handler(void *userData, | |
108 | const XML_Char *elname, | |
109 | const XML_Char *attname, | |
110 | const XML_Char *att_type, | |
111 | const XML_Char *dflt, | |
112 | int isrequired) | |
113 | {} | |
114 | ||
115 | static void | |
116 | dummy_comment_handler(void *userData, const XML_Char *data) | |
117 | {} | |
118 | ||
119 | static void | |
120 | dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data) | |
121 | {} | |
122 | ||
123 | static void | |
124 | dummy_start_element(void *userData, | |
125 | const XML_Char *name, const XML_Char **atts) | |
126 | {} | |
127 | ||
128 | ||
129 | /* | |
130 | * Character & encoding tests. | |
131 | */ | |
132 | ||
133 | START_TEST(test_nul_byte) | |
134 | { | |
135 | char text[] = "<doc>\0</doc>"; | |
136 | ||
137 | /* test that a NUL byte (in US-ASCII data) is an error */ | |
138 | if (XML_Parse(parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_OK) | |
139 | fail("Parser did not report error on NUL-byte."); | |
140 | if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN) | |
141 | xml_failure(parser); | |
142 | } | |
143 | END_TEST | |
144 | ||
145 | ||
146 | START_TEST(test_u0000_char) | |
147 | { | |
148 | /* test that a NUL byte (in US-ASCII data) is an error */ | |
149 | expect_failure("<doc>�</doc>", | |
150 | XML_ERROR_BAD_CHAR_REF, | |
151 | "Parser did not report error on NUL-byte."); | |
152 | } | |
153 | END_TEST | |
154 | ||
155 | START_TEST(test_bom_utf8) | |
156 | { | |
157 | /* This test is really just making sure we don't core on a UTF-8 BOM. */ | |
158 | char *text = "\357\273\277<e/>"; | |
159 | ||
160 | if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) | |
161 | xml_failure(parser); | |
162 | } | |
163 | END_TEST | |
164 | ||
165 | START_TEST(test_bom_utf16_be) | |
166 | { | |
167 | char text[] = "\376\377\0<\0e\0/\0>"; | |
168 | ||
169 | if (XML_Parse(parser, text, sizeof(text)-1, XML_TRUE) == XML_STATUS_ERROR) | |
170 | xml_failure(parser); | |
171 | } | |
172 | END_TEST | |
173 | ||
174 | START_TEST(test_bom_utf16_le) | |
175 | { | |
176 | char text[] = "\377\376<\0e\0/\0>\0"; | |
177 | ||
178 | if (XML_Parse(parser, text, sizeof(text)-1, XML_TRUE) == XML_STATUS_ERROR) | |
179 | xml_failure(parser); | |
180 | } | |
181 | END_TEST | |
182 | ||
183 | static void | |
184 | accumulate_characters(void *userData, const XML_Char *s, int len) | |
185 | { | |
186 | CharData_AppendXMLChars((CharData *)userData, s, len); | |
187 | } | |
188 | ||
189 | static void | |
190 | accumulate_attribute(void *userData, const XML_Char *name, | |
191 | const XML_Char **atts) | |
192 | { | |
193 | CharData *storage = (CharData *)userData; | |
194 | if (storage->count < 0 && atts != NULL && atts[0] != NULL) { | |
195 | /* "accumulate" the value of the first attribute we see */ | |
196 | CharData_AppendXMLChars(storage, atts[1], -1); | |
197 | } | |
198 | } | |
199 | ||
200 | ||
201 | static void | |
202 | _run_character_check(XML_Char *text, XML_Char *expected, | |
203 | const char *file, int line) | |
204 | { | |
205 | CharData storage; | |
206 | ||
207 | CharData_Init(&storage); | |
208 | XML_SetUserData(parser, &storage); | |
209 | XML_SetCharacterDataHandler(parser, accumulate_characters); | |
210 | if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) | |
211 | _xml_failure(parser, file, line); | |
212 | CharData_CheckXMLChars(&storage, expected); | |
213 | } | |
214 | ||
215 | #define run_character_check(text, expected) \ | |
216 | _run_character_check(text, expected, __FILE__, __LINE__) | |
217 | ||
218 | static void | |
219 | _run_attribute_check(XML_Char *text, XML_Char *expected, | |
220 | const char *file, int line) | |
221 | { | |
222 | CharData storage; | |
223 | ||
224 | CharData_Init(&storage); | |
225 | XML_SetUserData(parser, &storage); | |
226 | XML_SetStartElementHandler(parser, accumulate_attribute); | |
227 | if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) | |
228 | _xml_failure(parser, file, line); | |
229 | CharData_CheckXMLChars(&storage, expected); | |
230 | } | |
231 | ||
232 | #define run_attribute_check(text, expected) \ | |
233 | _run_attribute_check(text, expected, __FILE__, __LINE__) | |
234 | ||
235 | /* Regression test for SF bug #491986. */ | |
236 | START_TEST(test_danish_latin1) | |
237 | { | |
238 | char *text = | |
239 | "<?xml version='1.0' encoding='iso-8859-1'?>\n" | |
240 |