summaryrefslogtreecommitdiffstats
path: root/src/oplist.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2026-01-17 15:18:06 +0100
committerGravatar Nikias Bassen2026-01-17 16:04:00 +0100
commite45099fb21b679aa0cdb0db394587bb5ba675b0c (patch)
treeb1a2c1dd34877d83a04d6d6fab804fb2e5a65f2d /src/oplist.c
parent26dd27c435a0d110c924e1fef34ad0f6ae60e251 (diff)
downloadlibplist-e45099fb21b679aa0cdb0db394587bb5ba675b0c.tar.gz
libplist-e45099fb21b679aa0cdb0db394587bb5ba675b0c.tar.bz2
Prevent deep nesting of plist structures in all input/output formats
Thanks to @unbengable12 for reporting. Addresses #288, #289, #290, #291, and #292.
Diffstat (limited to 'src/oplist.c')
-rw-r--r--src/oplist.c69
1 files changed, 37 insertions, 32 deletions
diff --git a/src/oplist.c b/src/oplist.c
index 680873c..0eea27a 100644
--- a/src/oplist.c
+++ b/src/oplist.c
@@ -367,6 +367,11 @@ static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t dep
return PLIST_ERR_INVALID_ARG;
}
+ if (depth > PLIST_MAX_NESTING_DEPTH) {
+ PLIST_OSTEP_WRITE_ERR("node tree is nested too deeply\n");
+ return PLIST_ERR_MAX_NESTING;
+ }
+
if (hash_table_lookup(visited, node)) {
PLIST_OSTEP_WRITE_ERR("circular reference detected\n");
return PLIST_ERR_CIRCULAR_REF;
@@ -511,7 +516,7 @@ struct _parse_ctx {
const char *start;
const char *pos;
const char *end;
- int err;
+ plist_err_t err;
uint32_t depth;
};
typedef struct _parse_ctx* parse_ctx;
@@ -568,50 +573,50 @@ static void parse_dict_data(parse_ctx ctx, plist_t dict)
}
key = NULL;
ctx->err = node_from_openstep(ctx, &key);
- if (ctx->err != 0) {
+ if (ctx->err != PLIST_ERR_SUCCESS) {
break;
}
if (!PLIST_IS_STRING(key)) {
PLIST_OSTEP_ERR("Invalid type for dictionary key at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
parse_skip_ws(ctx);
if (ctx->pos >= ctx->end) {
PLIST_OSTEP_ERR("EOF while parsing dictionary '=' delimiter at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
if (*ctx->pos != '=') {
PLIST_OSTEP_ERR("Missing '=' while parsing dictionary item at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
ctx->pos++;
if (ctx->pos >= ctx->end) {
PLIST_OSTEP_ERR("EOF while parsing dictionary item at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
val = NULL;
ctx->err = node_from_openstep(ctx, &val);
- if (ctx->err != 0) {
+ if (ctx->err != PLIST_ERR_SUCCESS) {
break;
}
if (!val) {
PLIST_OSTEP_ERR("Missing value for dictionary item at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
parse_skip_ws(ctx);
if (ctx->pos >= ctx->end) {
PLIST_OSTEP_ERR("EOF while parsing dictionary item terminator ';' at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
if (*ctx->pos != ';') {
PLIST_OSTEP_ERR("Missing terminating ';' while parsing dictionary item at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
@@ -631,10 +636,10 @@ static plist_err_t node_from_openstep(parse_ctx ctx, plist_t *plist)
plist_t subnode = NULL;
const char *p = NULL;
ctx->depth++;
- if (ctx->depth > 1000) {
+ if (ctx->depth > PLIST_MAX_NESTING_DEPTH) {
PLIST_OSTEP_ERR("Too many levels of recursion (%u) at offset %ld\n", ctx->depth, (long int)(ctx->pos - ctx->start));
- ctx->err++;
- return PLIST_ERR_PARSE;
+ ctx->err = PLIST_ERR_MAX_NESTING;
+ return ctx->err;
}
while (ctx->pos < ctx->end && !ctx->err) {
parse_skip_ws(ctx);
@@ -652,12 +657,12 @@ static plist_err_t node_from_openstep(parse_ctx ctx, plist_t *plist)
}
if (ctx->pos >= ctx->end) {
PLIST_OSTEP_ERR("EOF while parsing dictionary terminator '}' at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
if (*ctx->pos != '}') {
PLIST_OSTEP_ERR("Missing terminating '}' at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
goto err_out;
}
ctx->pos++;
@@ -675,11 +680,11 @@ static plist_err_t node_from_openstep(parse_ctx ctx, plist_t *plist)
break;
}
ctx->err = node_from_openstep(ctx, &tmp);
- if (ctx->err != 0) {
+ if (ctx->err != PLIST_ERR_SUCCESS) {
break;
}
if (!tmp) {
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
plist_array_append_item(subnode, tmp);
@@ -687,7 +692,7 @@ static plist_err_t node_from_openstep(parse_ctx ctx, plist_t *plist)
parse_skip_ws(ctx);
if (ctx->pos >= ctx->end) {
PLIST_OSTEP_ERR("EOF while parsing array item delimiter ',' at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
if (*ctx->pos != ',') {
@@ -697,17 +702,17 @@ static plist_err_t node_from_openstep(parse_ctx ctx, plist_t *plist)
}
plist_free(tmp);
tmp = NULL;
- if (ctx->err) {
+ if (ctx->err != PLIST_ERR_SUCCESS) {
goto err_out;
}
if (ctx->pos >= ctx->end) {
PLIST_OSTEP_ERR("EOF while parsing array terminator ')' at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
if (*ctx->pos != ')') {
PLIST_OSTEP_ERR("Missing terminating ')' at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
goto err_out;
}
ctx->pos++;
@@ -722,7 +727,7 @@ static plist_err_t node_from_openstep(parse_ctx ctx, plist_t *plist)
parse_skip_ws(ctx);
if (ctx->pos >= ctx->end) {
PLIST_OSTEP_ERR("EOF while parsing data terminator '>' at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
if (*ctx->pos == '>') {
@@ -730,19 +735,19 @@ static plist_err_t node_from_openstep(parse_ctx ctx, plist_t *plist)
}
if (!isxdigit(*ctx->pos)) {
PLIST_OSTEP_ERR("Invalid byte group in data at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
uint8_t b = HEX_DIGIT(*ctx->pos);
ctx->pos++;
if (ctx->pos >= ctx->end) {
PLIST_OSTEP_ERR("Unexpected end of data at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
if (!isxdigit(*ctx->pos)) {
PLIST_OSTEP_ERR("Invalid byte group in data at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
b = (b << 4) + HEX_DIGIT(*ctx->pos);
@@ -758,14 +763,14 @@ static plist_err_t node_from_openstep(parse_ctx ctx, plist_t *plist)
byte_array_free(bytes);
plist_free_data(data);
PLIST_OSTEP_ERR("EOF while parsing data terminator '>' at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
goto err_out;
}
if (*ctx->pos != '>') {
byte_array_free(bytes);
plist_free_data(data);
PLIST_OSTEP_ERR("Missing terminating '>' at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
goto err_out;
}
ctx->pos++;
@@ -793,13 +798,13 @@ static plist_err_t node_from_openstep(parse_ctx ctx, plist_t *plist)
if (ctx->pos >= ctx->end) {
plist_free_data(data);
PLIST_OSTEP_ERR("EOF while parsing quoted string at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
goto err_out;
}
if (*ctx->pos != c) {
plist_free_data(data);
PLIST_OSTEP_ERR("Missing closing quote (%c) at offset %ld\n", c, (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
goto err_out;
}
size_t slen = ctx->pos - p;
@@ -900,7 +905,7 @@ static plist_err_t node_from_openstep(parse_ctx ctx, plist_t *plist)
} else {
plist_free_data(data);
PLIST_OSTEP_ERR("Unexpected character when parsing unquoted string at offset %ld\n", (long int)(ctx->pos - ctx->start));
- ctx->err++;
+ ctx->err = PLIST_ERR_PARSE;
break;
}
}
@@ -909,11 +914,11 @@ static plist_err_t node_from_openstep(parse_ctx ctx, plist_t *plist)
ctx->depth--;
err_out:
- if (ctx->err) {
+ if (ctx->err != PLIST_ERR_SUCCESS) {
plist_free(subnode);
plist_free(*plist);
*plist = NULL;
- return PLIST_ERR_PARSE;
+ return ctx->err;
}
return PLIST_ERR_SUCCESS;
}