summaryrefslogtreecommitdiffstats
path: root/src/xplist.c
AgeCommit message (Collapse)AuthorFilesLines
10 hoursHarden allocation failure handling and size arithmeticGravatar Nikias Bassen1-20/+77
- check malloc/calloc/realloc results in constructors, the JSON and OpenStep writers, the XML text-part helpers and base64 decoding, and return PLIST_ERR_NO_MEM instead of asserting or dereferencing NULL - guard size calculations against overflow in the UTF-8/UTF-16BE conversions, ptrarray, and bytearray - make hash_table_insert() report failure instead of silently dropping the entry; writers propagate PLIST_ERR_NO_MEM, and dict lookup caches are discarded so lookups fall back to a linear search - don't overwrite an earlier parse error code in the XML parser, and report PLIST_ERR_NO_MEM when reading text content fails for lack of memory - OpenStep parser: check node/data/string allocations and dict/array insertion results Based on #323 by bg0d-droid. Co-authored-by: bg0d-droid <81825610+bg0d-droid@users.noreply.github.com>
10 hoursxplist: fix double-free in node_from_xml() error pathsGravatar Nikias Bassen1-5/+9
node_from_xml() hands a freshly created node over to the tree (as root, or by adding it to a dict/array parent), but only reset `subnode` at the very end of the block. If an error occurred in between, e.g. the allocation of the node path item failing right after the root node was assigned to *plist, err_out freed the node while the tree still referenced it, and plist_free(*plist) then freed it a second time. Clear `subnode` right after the node has been successfully attached so that err_out can never free a node owned by the tree. Also report PLIST_ERR_NO_MEM instead of PLIST_ERR_PARSE when allocating the node path item fails. Co-authored-by: bg0d-droid <81825610+bg0d-droid@users.noreply.github.com>
12 hoursxplist: fix memory leak when adding a node to its parent failsGravatar Nikias Bassen1-2/+10
node_from_xml() ignored the return values of plist_dict_set_item() and plist_array_append_item(). When the insertion failed (e.g. when the nesting depth limit is hit in node_attach()), the newly created node was never attached, yet subnode was reset to NULL, so the node, its data and its string value were leaked. Check the return values and bail out with PLIST_ERR_PARSE so that the unattached node is freed in the error path. Credit to OSSFuzz
2026-09-29bytearray: Handle realloc() failure in byte_array_grow()Gravatar Comtea041-0/+10
byte_array_grow() assigned the result of realloc() directly to ba->data and increased the capacity even if realloc() failed, so the following memcpy() in byte_array_append() wrote to NULL + len. On failure, free the old buffer and leave the byte array in a failed state (data == NULL), which byte_array_append() already ignores. The callers check for that state: - the writers (bin, xml, json, openstep and the text output formats) return PLIST_ERR_NO_MEM instead of handing out a NULL/truncated buffer - node_to_xml() base64-encodes <data> directly into the grown buffer, so it must bail out there (only guarded by assert() before) - the OpenStep parser returns PLIST_ERR_NO_MEM for <hex data> instead of silently returning truncated data Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-05-22Print debug error message when encoutering invalid PLIST_DATE valuesGravatar Nikias Bassen1-0/+1
2026-05-22common: validate PLIST_DATE values before Time64_T conversionGravatar Nikias Bassen1-1/+4
Avoid undefined behavior when serializing malformed PLIST_DATE values containing NaN, infinity, or values outside the Time64_T range. Add a shared helper for checked date conversion and use it across writer paths.
2026-05-22refactor: centralize formatting helpers and harden out-plutilGravatar Nikias Bassen1-64/+1
2026-02-25xplist: Enforce single root value inside <plist>Gravatar Sami Kortelainen1-15/+17
Ensure that XML property lists contain exactly one root value inside the <plist> element and reject any additional value nodes before </plist>. Add tests covering root value handling and nested CF$UID conversion behavior. Co-authored-by: Sami Kortelainen <sami.kortelainen@piceasoft.com> Co-authored-by: Nikias Bassen <nikias@gmx.li>
2026-02-22xplist: Convert nested {CF$UID:<int>} dicts to PLIST_UID safelyGravatar Sami Kortelainen1-0/+20
Convert single-entry { "CF$UID" : <integer> } dictionaries to PLIST_UID nodes when closing a dict in the XML parser. Refactor node cleanup logic: - Split plist_free_data() into internal _plist_free_data() - Introduce plist_free_children() to release child nodes separately - Update plist_set_element_val() to free children before changing container node types - Ensure PLIST_DICT hashtables do not free values (assert + force free_func = NULL) This avoids in-place container mutation issues and ensures child nodes and container metadata are released correctly before changing node type. Co-authored-by: Sami Kortelainen <sami.kortelainen@piceasoft.com> Co-authored-by: Nikias Bassen <nikias@gmx.li>
2026-02-12Add NULL checks across codebaseGravatar Nikias Bassen1-0/+16
2026-01-29xplist: Improve robustness of XML text parsing and value conversionGravatar Nikias Bassen1-69/+152
This change adds stricter validation for numeric and date nodes, including full-input consumption, overflow/range checks, and rejection of invalid floating-point values. Whitespace handling is clarified by explicitly trimming trailing XML whitespace for value nodes.
2026-01-26xplist: Use small stack buffer instead of dynamic allocationsGravatar Nikias Bassen1-31/+16
This removes the necessity for malloc failures and reduces overhead
2026-01-22xplist: Use memcpy instead of strncpy since we know the exact sizeGravatar Nikias Bassen1-3/+3
2026-01-22xplist: Harden entity unescaping against malformed inputGravatar Nikias Bassen1-18/+32
- Fix numeric character reference parsing - Enforce exact entity name matching - Guard against size_t underflow and oversized entities - Reject invalid Unicode code points
2026-01-17Prevent deep nesting of plist structures in all input/output formatsGravatar Nikias Bassen1-49/+62
Thanks to @unbengable12 for reporting. Addresses #288, #289, #290, #291, and #292.
2026-01-14Add circular reference detection to all format writersGravatar Nikias Bassen1-2/+24
Thanks to @LkkkLxy for pointing out the issue.
2025-11-14xplist: Allow empty key entry in PLIST_DICTGravatar Nikias Bassen1-1/+9
Even though this is weird, the DTD allows it. This commit will also make the XML output write `<key/>` and `<string/>` instead of `<key></key>` and `<string></string>` in case of empty key/string node.
2025-10-29xplist: Fix possible integer overflowGravatar Nikias Bassen1-2/+2
Thanks to @ylwango613 for reporting
2023-05-21Add explicit casts and fix return type mismatchesGravatar Nikias Bassen1-33/+33
2023-05-13Add space before PRI* macros, some compilers do not like itGravatar Nikias Bassen1-4/+4
2023-05-13Move PLIST_API to the headersGravatar Nikias Bassen1-2/+2
2023-02-07Fix build without --enable-debugGravatar Nikias Bassen1-0/+2
2023-02-07Add function to interface to allow enabling/disabling error/debug output for ↵Gravatar Nikias Bassen1-0/+5
the format parses This makes the `-d` option work in plistutil that wasn't doing anything
2023-02-06libcnary: Updated typedefs of node_t and node_list_t to contain pointerGravatar Nikias Bassen1-6/+5
This makes the code more readable. Obviously all the code that uses it is also updated.
2023-01-19xplist: Add missing newline to debug messageGravatar Nikias Bassen1-1/+1
2023-01-16Rename PLIST_UINT to PLIST_INT and add plist_new_int() and plist_get_int_val()Gravatar Nikias Bassen1-3/+3
This properly supports getting and setting signed or unsigned integer values. Also, a new helper function plist_int_val_is_negative() was added to determine if a given #PLIST_INT node has a negative value or not. The old type PLIST_UINT is defined as a macro with the value of PLIST_INT for backwards compatibility. This commit also adds int vs. uint support to the C++ interface, and the python bindings in a hopefully useful way.
2022-02-07xplist: Prevent undefined behavior by not trying to negate INT64_MINGravatar Nikias Bassen1-1/+1
2021-12-23xplist: Add special handling for PLIST_UID parsing from XMLGravatar Nikias Bassen1-5/+14
In XML, PLIST_UID nodes are stored as a dict with a "CF$UID" key and an integer value, so we want to make it a real PLIST_UID node internally.
2021-12-22Add a return value to plist_to_* and plist_from_* functionsGravatar Nikias Bassen1-16/+45
This way it can be easier determined why an import/export operation failed instead of just having a NULL result.
2021-12-19Add support for PLIST_NULL typeGravatar Nikias Bassen1-5/+19
2021-12-19Add new plist_mem_free() functionGravatar Nikias Bassen1-5/+0
Thanks to @azerg for bringing this to my attention. Instead of having multiple (internally identical) plist_*_free() functions, this commit introduces a single plist_mem_free() that can be used to free the memory allocated by plist_to_xml(), plist_to_bin(), plist_get_key_val(), plist_get_string_val(), and plist_get_data_val(). Note: This commit REMOVES plist_to_bin_free() and plist_to_xml_free().
2021-11-08xplist: Better size estimation for PLIST_REAL nodesGravatar Nikias Bassen1-2/+2
2021-06-22[clang-tidy] Remove casts to the same typeGravatar Rosen Penev1-1/+1
Found with google-readability-casting Signed-off-by: Rosen Penev <rosenp@gmail.com>
2021-01-25Replace malloc + memset with calloc where appropriateGravatar Rosen Penev1-2/+1
calloc is faster for big allocations. It's also simpler. Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-11-24Add parentheses to macros for better readabilityGravatar Rosen Penev1-1/+1
[clang-tidy] Found with bugprone-macro-parentheses Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-11-24Improve code readability by using explicit != 0 compare when using strncmpGravatar Rosen Penev1-4/+4
[clang-tidy] Found with bugprone-suspicious-string-compare Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-03Remove pointless return in void functionsGravatar Rosen Penev1-2/+0
[clang-tidy] Found with readability-redundant-control-flow Signed-off-by: Rosen Penev <rosenp@gmail.com>
2019-11-07xplist: Bail out when '.' is found while checking for ',' in double to ↵Gravatar Nikias Bassen1-0/+2
string conversion
2019-11-07Add plist_to_bin_free() and plist_to_xml_free() functions that free memory ↵Gravatar Nikias Bassen1-0/+5
allocated by plist_to_bin()/plist_to_xml()
2019-11-07xplist: Increase precision when converting PLIST_REAL nodes to XMLGravatar Nikias Bassen1-37/+16
2019-01-21xplist: Fix dtostr() inserting ':' to output string when fractional part ↵Gravatar Nikias Bassen1-2/+15
overflows
2018-12-17xplist: Write base64 directly to output buffer to improve memory usageGravatar Nikias Bassen1-5/+2
Now that we grow the output buffer enough before writing XML output we can just write the base64 encoded data directly to the ouput buffer instead of using a heap buffer that will then be copied to the output buffer. This makes writing XML output more memory efficient (and slightly faster).
2018-12-14xplist: Improve memory usage by estimating output buffer sizeGravatar Nikias Bassen1-2/+127
2018-12-14xplist: Fix writing of empty dict and array nodes to XMLGravatar Nikias Bassen1-8/+6
2018-12-11xplist: Fix segfault caused by recent changes in libcnaryGravatar Nikias Bassen1-1/+1
2018-12-10xplist: Prevent unnecessary reallocations when writing XML outputGravatar Nikias Bassen1-1/+4
2018-12-10Remove node_iterator and operate on node list directly to improve memory usageGravatar Nikias Bassen1-4/+1
2018-09-04xplist: Assert when number of child nodes of PLIST_DICT is not evenGravatar Nikias Bassen1-0/+3
This should only happen due to misuse of the library, e.g. when calling plist_free() on a node that is a value node in a PLIST_DICT without properly removing the dictionary entry (key/value pair) and then calling plist_to_xml() on that dictionary.
2018-07-25xplist: Fix typo in error messageGravatar Bastien Nocera1-1/+1
2017-04-02xplist: Plug another memory leakGravatar Nikias Bassen1-0/+3
Credit to OSS-Fuzz