summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2016-02-07 15:46:06 +0000
committerAmaury Pouly <amaury.pouly@gmail.com>2016-02-07 15:46:06 +0000
commit76190313071f5b316db33fe578ae94ec744b6a27 (patch)
treeb6f7b1883e61b54e11411919b4840c0249f84fe8
parent7d87ebb470bc4f02173ee0e1afd17e10a028e540 (diff)
downloadrockbox-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.cpp50
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
255bool 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
238template<typename T, typename U> 265template<typename T, typename U>
239bool parse_unsigned_text(U *node, T& res, xmlChar *content, error_context_t& ctx) 266bool 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
306bool 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
279bool parse_enum_elem(xmlNode *node, enum_t& reg, error_context_t& ctx) 314bool 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;