diff options
author | Nikias Bassen | 2023-01-18 19:29:48 +0100 |
---|---|---|
committer | Nikias Bassen | 2023-01-18 19:29:48 +0100 |
commit | 4c8844d2c55a1ec05fa50f5b76c0b8baeece134c (patch) | |
tree | 43652a63fc6ae9d58f81706832f32c95689cfa06 | |
parent | 85f5cbd3705b34fcc52009ca51d8167ab18764fa (diff) | |
download | libplist-4c8844d2c55a1ec05fa50f5b76c0b8baeece134c.tar.gz libplist-4c8844d2c55a1ec05fa50f5b76c0b8baeece134c.tar.bz2 |
oplist: Prevent too many levels of recursion to prevent stack overflow
Credit to OSS-Fuzz
-rw-r--r-- | src/oplist.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/src/oplist.c b/src/oplist.c index 4dd0df5..420cbd6 100644 --- a/src/oplist.c +++ b/src/oplist.c @@ -480,6 +480,7 @@ struct _parse_ctx { const char *pos; const char *end; int err; + uint32_t depth; }; typedef struct _parse_ctx* parse_ctx; @@ -597,6 +598,12 @@ static int node_from_openstep(parse_ctx ctx, plist_t *plist) { plist_t subnode = NULL; const char *p = NULL; + ctx->depth++; + if (ctx->depth > 1000) { + PLIST_OSTEP_ERR("Too many levels of recursion (%u) at offset %ld\n", ctx->depth, ctx->pos - ctx->start); + ctx->err++; + return PLIST_ERR_PARSE; + } while (ctx->pos < ctx->end && !ctx->err) { parse_skip_ws(ctx); if (ctx->pos >= ctx->end) { @@ -867,6 +874,7 @@ static int node_from_openstep(parse_ctx ctx, plist_t *plist) } ctx->pos++; } + ctx->depth--; err_out: if (ctx->err) { @@ -888,7 +896,7 @@ PLIST_API int plist_from_openstep(const char *plist_ostep, uint32_t length, plis return PLIST_ERR_INVALID_ARG; } - struct _parse_ctx ctx = { plist_ostep, plist_ostep, plist_ostep + length, 0 }; + struct _parse_ctx ctx = { plist_ostep, plist_ostep, plist_ostep + length, 0 , 0 }; int err = node_from_openstep(&ctx, plist); if (err == 0) { |