diff options
| author | 2026-11-05 09:35:33 +0100 | |
|---|---|---|
| committer | 2026-11-05 09:35:33 +0100 | |
| commit | 3e9c034c93fa6f59584ec179d3df1333f250c694 (patch) | |
| tree | 96444ba52f58f002229d1b6724082e7c27d3e426 /src/plist.c | |
| parent | fe3dc34dc3484006e12b403f7ceb06f0ad40b6f4 (diff) | |
| download | libplist-3e9c034c93fa6f59584ec179d3df1333f250c694.tar.gz libplist-3e9c034c93fa6f59584ec179d3df1333f250c694.tar.bz2 | |
plist: fix use-after-free in plist_copy_node() on stack realloc
plist_copy_node() kept a pointer `f` to the top frame of its traversal
stack and dereferenced it after the stack was grown with realloc(),
which may move the buffer. Plists nested deeper than 64 levels hit this
path, causing a heap-use-after-free when reading f->depth.
Read the child depth before the realloc and use it when building the
new frame.
Thanks to @sdnuhfiu for reporting!
Fixes #328
Diffstat (limited to 'src/plist.c')
| -rw-r--r-- | src/plist.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/src/plist.c b/src/plist.c index bcd212c..66fe1ab 100644 --- a/src/plist.c +++ b/src/plist.c @@ -921,6 +921,8 @@ static plist_t plist_copy_node(node_t root) f->node_index++; // push child frame to process its children + // (read depth before realloc, which may invalidate f) + int child_depth = f->depth + 1; if (sp == cap) { cap += 64; copy_frame_t *tmp = (copy_frame_t*)realloc(st, cap * sizeof(*st)); @@ -940,7 +942,7 @@ static plist_t plist_copy_node(node_t root) nf.type = newch_type; nf.next_child = node_first_child(ch); nf.node_index = 0; - nf.depth = f->depth + 1; + nf.depth = child_depth; st[sp++] = nf; } |
