diff options
-rw-r--r-- | src/xplist.c | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/src/xplist.c b/src/xplist.c index 250b623..ec75226 100644 --- a/src/xplist.c +++ b/src/xplist.c @@ -762,7 +762,7 @@ static char* text_parts_get_content(text_part_t *tp, int unesc_entities, size_t return str; } -static void node_from_xml(parse_ctx ctx, plist_t *plist) +static void node_from_xml(parse_ctx ctx, plist_t *plist, uint32_t depth) { char *keyname = NULL; while (ctx->pos < ctx->end && !ctx->err) { @@ -886,9 +886,22 @@ static void node_from_xml(parse_ctx ctx, plist_t *plist) } if (!*plist) { /* only process first plist node found */ - node_from_xml(ctx, plist); + node_from_xml(ctx, plist, depth+1); } continue; + } else if (depth == 1 && !strcmp(tag, "/plist")) { + if (!*plist) { + PLIST_XML_ERR("Empty plist tag\n"); + } + free(tag); + free(keyname); + return; + } else if (depth == 1 && *plist) { + PLIST_XML_ERR("Unexpected tag %s found while /plist is expected\n", tag); + ctx->err++; + free(tag); + free(keyname); + return; } plist_data_t data = plist_new_plist_data(); @@ -1128,7 +1141,7 @@ static void node_from_xml(parse_ctx ctx, plist_t *plist) if (data->type == PLIST_DICT || data->type == PLIST_ARRAY) { if (!is_empty) { /* only if not empty */ - node_from_xml(ctx, &subnode); + node_from_xml(ctx, &subnode, depth+1); if (ctx->err) { /* make sure to bail out if parsing failed */ free(keyname); @@ -1176,9 +1189,30 @@ static void node_from_xml(parse_ctx ctx, plist_t *plist) break; } } - } else if (closing_tag && *plist && plist_get_node_type(*plist) == PLIST_DICT && keyname) { - PLIST_XML_ERR("missing value node in dict\n"); - ctx->err++; + } else if (closing_tag && *plist) { + switch (plist_get_node_type(*plist)) { + case PLIST_DICT: + if (keyname) { + PLIST_XML_ERR("missing value node in dict\n"); + ctx->err++; + } else if (strcmp(tag+1, XPLIST_DICT) != 0) { + PLIST_XML_ERR("closing tag mismatch, expected: /%s found: %s\n", XPLIST_DICT, tag); + ctx->err++; + } + break; + case PLIST_ARRAY: + if (strcmp(tag+1, XPLIST_ARRAY) != 0) { + PLIST_XML_ERR("closing tag mismatch, expected: /%s found: %s\n", XPLIST_ARRAY, tag); + ctx->err++; + } + break; + default: + /* should not happen */ + PLIST_XML_ERR("expected structered node but got type %d\n", plist_get_node_type(*plist)); + ctx->err++; + break; + } + break; } free(keyname); keyname = NULL; @@ -1188,6 +1222,10 @@ static void node_from_xml(parse_ctx ctx, plist_t *plist) } } } + if (depth == 1) { + PLIST_XML_ERR("EOF while /plist tag is expected\n"); + ctx->err++; + } if (ctx->err) { plist_free(*plist); *plist = NULL; @@ -1203,5 +1241,5 @@ PLIST_API void plist_from_xml(const char *plist_xml, uint32_t length, plist_t * struct _parse_ctx ctx = { plist_xml, plist_xml + length, 0 }; - node_from_xml(&ctx, plist); + node_from_xml(&ctx, plist, 0); } |