diff options
| author | 2026-01-14 02:50:40 +0100 | |
|---|---|---|
| committer | 2026-01-14 02:50:40 +0100 | |
| commit | 5b3ae4c1326e0c85df906ffea49b97b80b13ceae (patch) | |
| tree | a6efdca6333188abf924e13cb70a7aae49665ae1 /src/oplist.c | |
| parent | 25d61ff8b5d994a02c0cc2af8e029bebd3a94cb3 (diff) | |
| download | libplist-5b3ae4c1326e0c85df906ffea49b97b80b13ceae.tar.gz libplist-5b3ae4c1326e0c85df906ffea49b97b80b13ceae.tar.bz2 | |
Add circular reference detection to all format writers
Thanks to @LkkkLxy for pointing out the issue.
Diffstat (limited to 'src/oplist.c')
| -rw-r--r-- | src/oplist.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/src/oplist.c b/src/oplist.c index 277693f..680873c 100644 --- a/src/oplist.c +++ b/src/oplist.c @@ -37,6 +37,7 @@ #include "plist.h" #include "strbuf.h" +#include "hashtable.h" #ifdef DEBUG static int plist_ostep_debug = 0; @@ -359,18 +360,27 @@ static int num_digits_u(uint64_t i) return n; } -static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify) +static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify, hashtable_t *visited) { plist_data_t data; if (!node) { return PLIST_ERR_INVALID_ARG; } + + if (hash_table_lookup(visited, node)) { + PLIST_OSTEP_WRITE_ERR("circular reference detected\n"); + return PLIST_ERR_CIRCULAR_REF; + } + + // mark as visited + hash_table_insert(visited, node, (void*)1); + data = plist_get_data(node); if (node->children) { node_t ch; unsigned int n_children = node_n_children(node); for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { - plist_err_t res = node_estimate_size(ch, size, depth + 1, prettify); + plist_err_t res = _node_estimate_size(ch, size, depth + 1, prettify, visited); if (res < 0) { return res; } @@ -446,6 +456,15 @@ static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t dept return PLIST_ERR_SUCCESS; } +static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify) +{ + hashtable_t *visited = hash_table_new(plist_node_ptr_hash, plist_node_ptr_compare, NULL); + if (!visited) return PLIST_ERR_NO_MEM; + plist_err_t err = _node_estimate_size(node, size, depth, prettify, visited); + hash_table_destroy(visited); + return err; +} + plist_err_t plist_to_openstep(plist_t plist, char **openstep, uint32_t* length, int prettify) { uint64_t size = 0; |
