summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/xplist.c52
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);
}