| Age | Commit message (Collapse) | Author | Files | Lines |
|
plist_dict_get_bool() compared the string value with strcmp() but treated a
non-zero return as a match. strcmp() returns 0 on equality, so the conditions
were inverted: "true" produced 0, "false" produced 1, and any other string
also produced 1. The error branch could never be reached, since it required
both comparisons to return 0 at once.
The result is that the API returns the opposite of the stored value for both
valid boolean strings, and returns true for strings that are not booleans at
all, instead of reporting the conversion error.
Compare == 0 in both conditions:
input before after
true 0 1
false 1 0
not-a-bool 1 error
TRUE 1 error
(empty) 1 error
Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
|
|
ptr_array_insert() assigned the result of realloc() directly to
pa->pdata and bumped the capacity without checking for failure, so on
out-of-memory the old buffer was leaked and the following store or
memmove() wrote through a NULL pointer.
Keep the old buffer on failure and return -1 from ptr_array_insert()
and ptr_array_add(). The callers now handle the error:
- the array lookup cache (plist.c) is dropped instead of silently going
out of sync with the node list; lookups then fall back to walking
the children, as they do before the cache exists
- bplist parsing (used_indexes) and serialization (objects) return
PLIST_ERR_NO_MEM; ignoring the error in parse_bin_node_at_index()
would otherwise loop forever since the array never grows
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
|
|
Convert all array/dict modification functions from void to plist_err_t return type:
- plist_array_set_item: replace at index n
- plist_array_append_item: append to end
- plist_array_insert_item: insert at position n
- plist_array_remove_item: remove item at index n
- plist_array_item_remove: remove item from its array parent
- plist_dict_set_item: replace or insert key/value
- plist_dict_remove_item: remove key/value pair
- plist_dict_merge: merge source dict into target
Returns:
- PLIST_ERR_SUCCESS on success
- PLIST_ERR_INVALID_ARG for invalid arguments (NULL, wrong type, out of range, etc.)
- PLIST_ERR_NO_MEM on memory allocation failure
- PLIST_ERR_UNKNOWN on unexpected internal errors
Header documentation updated with full error code semantics for each function.
|
|
- Use PLIST_OPT_COERCE option to coerce PLIST_BOOLEAN, PLIST_DATE, PLIST_UID, and PLIST_NULL to OpenStep-compatible types (1 or 0, ISO 8601 strings, integers, and 'NULL' string)
- Add plist_to_openstep_with_options() function to allow passing coercion option (and others)
- Update plist_write_to_string() and plist_write_to_stream() accordingly
|
|
- Add PLIST_OPT_COERCE option to coerce PLIST_DATE, PLIST_DATA, and PLIST_UID to JSON-compatible types (ISO 8601 strings, Base64 strings, and integers)
- Add plist_to_json_with_options() function to allow passing coercion options (and others)
- Update plist_write_to_string() and plist_write_to_stream() to support coercion option
- Add --coerce flag to plistutil for JSON output
- Create plist2json symlink that automatically enables coercion when invoked
|
|
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>
|
|
Introduce private iterator structs for plist_array_iter and
plist_dict_iter, and fix *_next_item() to properly advance
iterator state and handle malformed containers safely.
|
|
|
|
Convert plist_free_node() and plist_copy_node() to iterative
implementations. This avoids unbounded recursion and stack
overflow when handling deeply nested plist data, while
preserving existing semantics and caches.
|
|
Update plist array and dict mutation helpers to check
return values from node_attach() and node_insert(). This
prevents cache corruption and allows new depth and cycle
checks to be enforced correctly.
|
|
Use explicit key/value stepping, zero-initialize hash lookup key,
and perform length-checked comparisons on NUL-terminated key strings.
|
|
Fixes issue #300
Credit to @jasonmli8
|
|
|
|
Credit to @LkkkLxy. Addresses #277.
|
|
Credit to @LkkkLxy for reporting (#276).
libplist nodes are owned by exactly one container. Inserting the same
plist_t into multiple dicts or arrays corrupts the tree structure and
leads to use-after-free crashes during traversal or plist_free().
Add explicit parent checks to dict and array insertion APIs to reject
nodes that already belong to another container. In debug builds, this
fails loudly via assert() and optional diagnostics; in release builds,
the operation safely no-ops.
Callers that need to reuse values must create a copy using plist_copy()
or explicitly detach the node before reinserting it.
|
|
Ensure plist_data_compare safely handles NULL inputs by normalizing
NULL data to empty values and avoiding invalid dereferences.
|
|
|
|
plist_date_val_compare calls plist_get_date_val which is now marked
deprecated. To avoid compiler warnings during build, we use the underlying
implementation directly instead of calling the function to work around it.
|
|
functions
These functions work with int64_t values representing a UNIX timestamp instead
of using the 'MAC epoch'. They should be used instead of plist_new_date,
plist_get_date_val, and plist_set_date_val, which are now marked deprecated
and might be removed in a future version of libplist.
|
|
Otherwise the internal assertion will trigger since the incorrect
size will be checked against.
Thanks to @michaelwright235, @guyingzhao, and others for pointing this out!
|
|
Credit to @Anza2001
|
|
|
|
This prevents a bug class where we bswap things when __LITTLE_ENDIAN__ is not defined.
Almost all modern systems are little endian, so detecting __BIG_ENDIAN__ is a better strategy.
|
|
|
|
This reverts commit a91f5740d100414a76959714b819422ee5b2d8a8.
|
|
|
|
This makes it more obvious that it is arbitrary data and not necessarily
a string value.
|
|
|
|
Credit to OSS-Fuzz
|
|
Thanks to @tihmstar for pointing this out!
|
|
Thanks @beyonik for pointing this out!
|
|
|
|
|
|
|
|
|
|
|
|
plist_read_from_file() is a convenience function that will open a
given file, checks its size, allocates a buffer large enough to
hold the full contents, and reads from file to fill the buffer.
Then, it calls plist_from_memory() to convert the data to plist
format.
A (breaking) change had to be made so that plist_from_memory() will
also return the parsed format in its 4th argument (if non-NULL).
|
|
This commit introduces constants for the different plist formats,
and adds 3 new human-readable output-only formats:
- PLIST_FORMAT_PRINT: the default human-readable format
- PLIST_FORMAT_LIMD: "libimobiledevice" format (used in ideviceinfo)
- PLIST_FORMAT_PLUTIL: plutil-style format
Also, a new set of write functions has been added:
- plist_write_to_string
- plist_write_to_stream
- plist_write_to_file
Plus a simple "dump" function:
- plist_print
See documentation for details.
|
|
the format parses
This makes the `-d` option work in plistutil that wasn't doing anything
|
|
This makes the code more readable. Obviously all the code that uses it
is also updated.
|
|
The problem was that we swapped potential child node data between nodes,
but their parents would not be updated that way, leading to double frees
or segmentation faults when freeing a plist. This commit instead fixes this
by swapping the actual nodes in the tree.
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
This way it can be easier determined why an import/export operation failed
instead of just having a NULL result.
|