diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2016-02-07 15:46:06 +0000 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2016-02-07 15:46:06 +0000 |
commit | 76190313071f5b316db33fe578ae94ec744b6a27 (patch) | |
tree | b6f7b1883e61b54e11411919b4840c0249f84fe8 | |
parent | 7d87ebb470bc4f02173ee0e1afd17e10a028e540 (diff) | |
download | rockbox-76190313071f5b316db33fe578ae94ec744b6a27.tar.gz rockbox-76190313071f5b316db33fe578ae94ec744b6a27.zip |
regtools: make description file parser stricter
The parser would simply ignore unknown elements or attributes, which is bad
on many levels. Now any unknown tag will trigger a fatal error.
Change-Id: I32eead8e96c1567241cf2a565d9e20e62877c14d
-rw-r--r-- | utils/regtools/lib/soc_desc.cpp | 50 |
1 files changed, 48 insertions, 2 deletions
diff --git a/utils/regtools/lib/soc_desc.cpp b/utils/regtools/lib/soc_desc.cpp index e6c58d4814..a72e7e9f7c 100644 --- a/utils/regtools/lib/soc_desc.cpp +++ b/utils/regtools/lib/soc_desc.cpp | |||
@@ -40,7 +40,8 @@ namespace soc_desc | |||
40 | #define XML_CHAR_TO_CHAR(s) ((const char *)(s)) | 40 | #define XML_CHAR_TO_CHAR(s) ((const char *)(s)) |
41 | 41 | ||
42 | #define BEGIN_ATTR_MATCH(attr) \ | 42 | #define BEGIN_ATTR_MATCH(attr) \ |
43 | for(xmlAttr *a = attr; a; a = a->next) { | 43 | for(xmlAttr *a = attr; a; a = a->next) { \ |
44 | bool used = false; | ||
44 | 45 | ||
45 | #define MATCH_UNIQUE_ATTR(attr_name, val, has, parse_fn, ctx) \ | 46 | #define MATCH_UNIQUE_ATTR(attr_name, val, has, parse_fn, ctx) \ |
46 | if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \ | 47 | if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \ |
@@ -50,13 +51,20 @@ namespace soc_desc | |||
50 | xmlChar *str = NULL; \ | 51 | xmlChar *str = NULL; \ |
51 | if(!parse_text_attr_internal(a, str, ctx) || !parse_fn(a, val, str, ctx)) \ | 52 | if(!parse_text_attr_internal(a, str, ctx) || !parse_fn(a, val, str, ctx)) \ |
52 | ret = false; \ | 53 | ret = false; \ |
54 | used = true; \ | ||
55 | } | ||
56 | |||
57 | #define MATCH_UNUSED_ATTR(parse_fn, ctx) \ | ||
58 | if(!used) { \ | ||
59 | ret = ret && parse_fn(a, ctx); \ | ||
53 | } | 60 | } |
54 | 61 | ||
55 | #define END_ATTR_MATCH() \ | 62 | #define END_ATTR_MATCH() \ |
56 | } | 63 | } |
57 | 64 | ||
58 | #define BEGIN_NODE_MATCH(node) \ | 65 | #define BEGIN_NODE_MATCH(node) \ |
59 | for(xmlNode *sub = node; sub; sub = sub->next) { | 66 | for(xmlNode *sub = node; sub; sub = sub->next) { \ |
67 | bool used = false; \ | ||
60 | 68 | ||
61 | #define MATCH_ELEM_NODE(node_name, array, parse_fn, ctx) \ | 69 | #define MATCH_ELEM_NODE(node_name, array, parse_fn, ctx) \ |
62 | if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \ | 70 | if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \ |
@@ -64,6 +72,7 @@ namespace soc_desc | |||
64 | if(!parse_fn(sub, array.back(), ctx)) \ | 72 | if(!parse_fn(sub, array.back(), ctx)) \ |
65 | ret = false; \ | 73 | ret = false; \ |
66 | array.back().id = array.size(); \ | 74 | array.back().id = array.size(); \ |
75 | used = true; \ | ||
67 | } | 76 | } |
68 | 77 | ||
69 | #define MATCH_TEXT_NODE(node_name, array, parse_fn, ctx) \ | 78 | #define MATCH_TEXT_NODE(node_name, array, parse_fn, ctx) \ |
@@ -74,6 +83,7 @@ namespace soc_desc | |||
74 | array.resize(array.size() + 1); \ | 83 | array.resize(array.size() + 1); \ |
75 | ret = ret && parse_fn(sub, array.back(), content, ctx); \ | 84 | ret = ret && parse_fn(sub, array.back(), content, ctx); \ |
76 | xmlFree(content); \ | 85 | xmlFree(content); \ |
86 | used = true; \ | ||
77 | } | 87 | } |
78 | 88 | ||
79 | #define MATCH_UNIQUE_ELEM_NODE(node_name, val, has, parse_fn, ctx) \ | 89 | #define MATCH_UNIQUE_ELEM_NODE(node_name, val, has, parse_fn, ctx) \ |
@@ -83,6 +93,7 @@ namespace soc_desc | |||
83 | has = true; \ | 93 | has = true; \ |
84 | if(!parse_fn(sub, val, ctx)) \ | 94 | if(!parse_fn(sub, val, ctx)) \ |
85 | ret = false; \ | 95 | ret = false; \ |
96 | used = true; \ | ||
86 | } | 97 | } |
87 | 98 | ||
88 | #define MATCH_UNIQUE_TEXT_NODE(node_name, val, has, parse_fn, ctx) \ | 99 | #define MATCH_UNIQUE_TEXT_NODE(node_name, val, has, parse_fn, ctx) \ |
@@ -95,6 +106,12 @@ namespace soc_desc | |||
95 | xmlChar *content = xmlNodeGetContent(sub); \ | 106 | xmlChar *content = xmlNodeGetContent(sub); \ |
96 | ret = ret && parse_fn(sub, val, content, ctx); \ | 107 | ret = ret && parse_fn(sub, val, content, ctx); \ |
97 | xmlFree(content); \ | 108 | xmlFree(content); \ |
109 | used = true; \ | ||
110 | } | ||
111 | |||
112 | #define MATCH_UNUSED_NODE(parse_fn, ctx) \ | ||
113 | if(!used) { \ | ||
114 | ret = ret && parse_fn(sub, ctx); \ | ||
98 | } | 115 | } |
99 | 116 | ||
100 | #define END_NODE_MATCH() \ | 117 | #define END_NODE_MATCH() \ |
@@ -235,6 +252,16 @@ bool parse_name_elem(xmlNode *node, std::string& name, xmlChar *content, error_c | |||
235 | return true; | 252 | return true; |
236 | } | 253 | } |
237 | 254 | ||
255 | bool parse_unknown_elem(xmlNode *node, error_context_t& ctx) | ||
256 | { | ||
257 | /* ignore blank nodes */ | ||
258 | if(xmlIsBlankNode(node)) | ||
259 | return true; | ||
260 | std::ostringstream oss; | ||
261 | oss << "unknown <" << XML_CHAR_TO_CHAR(node->name) << "> element"; | ||
262 | return add_fatal(ctx, node, oss.str()); | ||
263 | } | ||
264 | |||
238 | template<typename T, typename U> | 265 | template<typename T, typename U> |
239 | bool parse_unsigned_text(U *node, T& res, xmlChar *content, error_context_t& ctx) | 266 | bool parse_unsigned_text(U *node, T& res, xmlChar *content, error_context_t& ctx) |
240 | { | 267 | { |
@@ -276,6 +303,14 @@ bool parse_text_attr(xmlAttr *attr, std::string& res, xmlChar *content, error_co | |||
276 | return true; | 303 | return true; |
277 | } | 304 | } |
278 | 305 | ||
306 | bool parse_unknown_attr(xmlAttr *attr, error_context_t& ctx) | ||
307 | { | ||
308 | std::ostringstream oss; | ||
309 | oss << "unknown '" << XML_CHAR_TO_CHAR(attr->name) << "' attribute"; | ||
310 | return add_fatal(ctx, attr, oss.str()); | ||
311 | } | ||
312 | |||
313 | |||
279 | bool parse_enum_elem(xmlNode *node, enum_t& reg, error_context_t& ctx) | 314 | bool parse_enum_elem(xmlNode *node, enum_t& reg, error_context_t& ctx) |
280 | { | 315 | { |
281 | bool ret = true; | 316 | bool ret = true; |
@@ -284,6 +319,7 @@ bool parse_enum_elem(xmlNode *node, enum_t& reg, error_context_t& ctx) | |||
284 | MATCH_UNIQUE_TEXT_NODE("name", reg.name, has_name, parse_name_elem, ctx) | 319 | MATCH_UNIQUE_TEXT_NODE("name", reg.name, has_name, parse_name_elem, ctx) |
285 | MATCH_UNIQUE_TEXT_NODE("value", reg.value, has_value, parse_unsigned_elem, ctx) | 320 | MATCH_UNIQUE_TEXT_NODE("value", reg.value, has_value, parse_unsigned_elem, ctx) |
286 | MATCH_UNIQUE_TEXT_NODE("desc", reg.desc, has_desc, parse_text_elem, ctx) | 321 | MATCH_UNIQUE_TEXT_NODE("desc", reg.desc, has_desc, parse_text_elem, ctx) |
322 | MATCH_UNUSED_NODE(parse_unknown_elem, ctx) | ||
287 | END_NODE_MATCH() | 323 | END_NODE_MATCH() |
288 | CHECK_HAS(node, "name", has_name, ctx) | 324 | CHECK_HAS(node, "name", has_name, ctx) |
289 | CHECK_HAS(node, "value", has_value, ctx) | 325 | CHECK_HAS(node, "value", has_value, ctx) |
@@ -300,6 +336,7 @@ bool parse_field_elem(xmlNode *node, field_t& field, error_context_t& ctx) | |||
300 | MATCH_UNIQUE_TEXT_NODE("width", field.width, has_width, parse_unsigned_elem, ctx) | 336 | MATCH_UNIQUE_TEXT_NODE("width", field.width, has_width, parse_unsigned_elem, ctx) |
301 | MATCH_UNIQUE_TEXT_NODE("desc", field.desc, has_desc, parse_text_elem, ctx) | 337 | MATCH_UNIQUE_TEXT_NODE("desc", field.desc, has_desc, parse_text_elem, ctx) |
302 | MATCH_ELEM_NODE("enum", field.enum_, parse_enum_elem, ctx) | 338 | MATCH_ELEM_NODE("enum", field.enum_, parse_enum_elem, ctx) |
339 | MATCH_UNUSED_NODE(parse_unknown_elem, ctx) | ||
303 | END_NODE_MATCH() | 340 | END_NODE_MATCH() |
304 | CHECK_HAS(node, "name", has_name, ctx) | 341 | CHECK_HAS(node, "name", has_name, ctx) |
305 | CHECK_HAS(node, "position", has_pos, ctx) | 342 | CHECK_HAS(node, "position", has_pos, ctx) |
@@ -315,6 +352,7 @@ bool parse_variant_elem(xmlNode *node, variant_t& variant, error_context_t& ctx) | |||
315 | BEGIN_NODE_MATCH(node->children) | 352 | BEGIN_NODE_MATCH(node->children) |
316 | MATCH_UNIQUE_TEXT_NODE("type", variant.type, has_type, parse_name_elem, ctx) | 353 | MATCH_UNIQUE_TEXT_NODE("type", variant.type, has_type, parse_name_elem, ctx) |
317 | MATCH_UNIQUE_TEXT_NODE("offset", variant.offset, has_offset, parse_unsigned_elem, ctx) | 354 | MATCH_UNIQUE_TEXT_NODE("offset", variant.offset, has_offset, parse_unsigned_elem, ctx) |
355 | MATCH_UNUSED_NODE(parse_unknown_elem, ctx) | ||
318 | END_NODE_MATCH() | 356 | END_NODE_MATCH() |
319 | CHECK_HAS(node, "type", has_type, ctx) | 357 | CHECK_HAS(node, "type", has_type, ctx) |
320 | CHECK_HAS(node, "offset", has_offset, ctx) | 358 | CHECK_HAS(node, "offset", has_offset, ctx) |
@@ -330,6 +368,7 @@ bool parse_register_elem(xmlNode *node, register_t& reg, error_context_t& ctx) | |||
330 | MATCH_UNIQUE_TEXT_NODE("width", reg.width, has_width, parse_unsigned_elem, ctx) | 368 | MATCH_UNIQUE_TEXT_NODE("width", reg.width, has_width, parse_unsigned_elem, ctx) |
331 | MATCH_ELEM_NODE("field", reg.field, parse_field_elem, ctx) | 369 | MATCH_ELEM_NODE("field", reg.field, parse_field_elem, ctx) |
332 | MATCH_ELEM_NODE("variant", reg.variant, parse_variant_elem, ctx) | 370 | MATCH_ELEM_NODE("variant", reg.variant, parse_variant_elem, ctx) |
371 | MATCH_UNUSED_NODE(parse_unknown_elem, ctx) | ||
333 | END_NODE_MATCH() | 372 | END_NODE_MATCH() |
334 | if(!has_width) | 373 | if(!has_width) |
335 | reg.width = 32; | 374 | reg.width = 32; |
@@ -342,6 +381,7 @@ bool parse_formula_elem(xmlNode *node, range_t& range, error_context_t& ctx) | |||
342 | bool has_var = false; | 381 | bool has_var = false; |
343 | BEGIN_ATTR_MATCH(node->properties) | 382 | BEGIN_ATTR_MATCH(node->properties) |
344 | MATCH_UNIQUE_ATTR("variable", range.variable, has_var, parse_text_attr, ctx) | 383 | MATCH_UNIQUE_ATTR("variable", range.variable, has_var, parse_text_attr, ctx) |
384 | MATCH_UNUSED_ATTR(parse_unknown_attr, ctx) | ||
345 | END_NODE_MATCH() | 385 | END_NODE_MATCH() |
346 | CHECK_HAS_ATTR(node, "variable", has_var, ctx) | 386 | CHECK_HAS_ATTR(node, "variable", has_var, ctx) |
347 | return ret; | 387 | return ret; |
@@ -360,6 +400,7 @@ bool parse_range_elem(xmlNode *node, range_t& range, error_context_t& ctx) | |||
360 | MATCH_UNIQUE_ELEM_NODE("formula", range, has_formula_attr, parse_formula_elem, ctx) | 400 | MATCH_UNIQUE_ELEM_NODE("formula", range, has_formula_attr, parse_formula_elem, ctx) |
361 | MATCH_UNIQUE_TEXT_NODE("formula", range.formula, has_formula, parse_text_elem, ctx) | 401 | MATCH_UNIQUE_TEXT_NODE("formula", range.formula, has_formula, parse_text_elem, ctx) |
362 | MATCH_TEXT_NODE("address", range.list, parse_unsigned_elem, ctx) | 402 | MATCH_TEXT_NODE("address", range.list, parse_unsigned_elem, ctx) |
403 | MATCH_UNUSED_NODE(parse_unknown_elem, ctx) | ||
363 | END_NODE_MATCH() | 404 | END_NODE_MATCH() |
364 | CHECK_HAS(node, "first", has_first, ctx) | 405 | CHECK_HAS(node, "first", has_first, ctx) |
365 | if(range.list.size() == 0) | 406 | if(range.list.size() == 0) |
@@ -404,6 +445,7 @@ bool parse_instance_elem(xmlNode *node, instance_t& inst, error_context_t& ctx) | |||
404 | MATCH_UNIQUE_TEXT_NODE("desc", inst.desc, has_desc, parse_text_elem, ctx) | 445 | MATCH_UNIQUE_TEXT_NODE("desc", inst.desc, has_desc, parse_text_elem, ctx) |
405 | MATCH_UNIQUE_TEXT_NODE("address", inst.addr, has_address, parse_unsigned_elem, ctx) | 446 | MATCH_UNIQUE_TEXT_NODE("address", inst.addr, has_address, parse_unsigned_elem, ctx) |
406 | MATCH_UNIQUE_ELEM_NODE("range", inst.range, has_range, parse_range_elem, ctx) | 447 | MATCH_UNIQUE_ELEM_NODE("range", inst.range, has_range, parse_range_elem, ctx) |
448 | MATCH_UNUSED_NODE(parse_unknown_elem, ctx) | ||
407 | END_NODE_MATCH() | 449 | END_NODE_MATCH() |
408 | CHECK_HAS(node, "name", has_name, ctx) | 450 | CHECK_HAS(node, "name", has_name, ctx) |
409 | if(!has_address && !has_range) | 451 | if(!has_address && !has_range) |
@@ -429,6 +471,7 @@ bool parse_node_elem(xmlNode *node_, node_t& node, error_context_t& ctx) | |||
429 | MATCH_UNIQUE_ELEM_NODE("register", reg, has_register, parse_register_elem, ctx) | 471 | MATCH_UNIQUE_ELEM_NODE("register", reg, has_register, parse_register_elem, ctx) |
430 | MATCH_ELEM_NODE("node", node.node, parse_node_elem, ctx) | 472 | MATCH_ELEM_NODE("node", node.node, parse_node_elem, ctx) |
431 | MATCH_ELEM_NODE("instance", node.instance, parse_instance_elem, ctx) | 473 | MATCH_ELEM_NODE("instance", node.instance, parse_instance_elem, ctx) |
474 | MATCH_UNUSED_NODE(parse_unknown_elem, ctx) | ||
432 | END_NODE_MATCH() | 475 | END_NODE_MATCH() |
433 | CHECK_HAS(node_, "name", has_name, ctx) | 476 | CHECK_HAS(node_, "name", has_name, ctx) |
434 | if(has_register) | 477 | if(has_register) |
@@ -449,6 +492,7 @@ bool parse_soc_elem(xmlNode *node, soc_t& soc, error_context_t& ctx) | |||
449 | MATCH_UNIQUE_TEXT_NODE("isa", soc.isa, has_isa, parse_text_elem, ctx) | 492 | MATCH_UNIQUE_TEXT_NODE("isa", soc.isa, has_isa, parse_text_elem, ctx) |
450 | MATCH_TEXT_NODE("author", soc.author, parse_text_elem, ctx) | 493 | MATCH_TEXT_NODE("author", soc.author, parse_text_elem, ctx) |
451 | MATCH_ELEM_NODE("node", soc.node, parse_node_elem, ctx) | 494 | MATCH_ELEM_NODE("node", soc.node, parse_node_elem, ctx) |
495 | MATCH_UNUSED_NODE(parse_unknown_elem, ctx) | ||
452 | END_NODE_MATCH() | 496 | END_NODE_MATCH() |
453 | CHECK_HAS(node, "name", has_name, ctx) | 497 | CHECK_HAS(node, "name", has_name, ctx) |
454 | return ret; | 498 | return ret; |
@@ -461,6 +505,7 @@ bool parse_root_elem(xmlNode *node, soc_t& soc, error_context_t& ctx) | |||
461 | bool has_soc = false, has_version = false; | 505 | bool has_soc = false, has_version = false; |
462 | BEGIN_ATTR_MATCH(node->properties) | 506 | BEGIN_ATTR_MATCH(node->properties) |
463 | MATCH_UNIQUE_ATTR("version", ver, has_version, parse_unsigned_attr, ctx) | 507 | MATCH_UNIQUE_ATTR("version", ver, has_version, parse_unsigned_attr, ctx) |
508 | MATCH_UNUSED_ATTR(parse_unknown_attr, ctx) | ||
464 | END_ATTR_MATCH() | 509 | END_ATTR_MATCH() |
465 | if(!has_version) | 510 | if(!has_version) |
466 | { | 511 | { |
@@ -471,6 +516,7 @@ bool parse_root_elem(xmlNode *node, soc_t& soc, error_context_t& ctx) | |||
471 | return parse_wrong_version_error(node, ctx); | 516 | return parse_wrong_version_error(node, ctx); |
472 | BEGIN_NODE_MATCH(node) | 517 | BEGIN_NODE_MATCH(node) |
473 | MATCH_UNIQUE_ELEM_NODE("soc", soc, has_soc, parse_soc_elem, ctx) | 518 | MATCH_UNIQUE_ELEM_NODE("soc", soc, has_soc, parse_soc_elem, ctx) |
519 | MATCH_UNUSED_NODE(parse_unknown_elem, ctx) | ||
474 | END_NODE_MATCH() | 520 | END_NODE_MATCH() |
475 | CHECK_HAS(node, "soc", has_soc, ctx) | 521 | CHECK_HAS(node, "soc", has_soc, ctx) |
476 | return ret; | 522 | return ret; |