-
-
Notifications
You must be signed in to change notification settings - Fork 328
Description
Issue: Integer copy constructor incorrectly handles negative values
Description
When copying a PList::Integer
object that contains a negative value, the copied object incorrectly represents the value as a large positive integer instead of preserving the original negative value.
Steps to Reproduce
#include <plist/plist++.h>
#include <string>
std::string to_xml(plist_t node) {
std::string ret;
char* s = nullptr;
uint32_t len = 0;
if (plist_to_xml(node, &s, &len) != PLIST_ERR_SUCCESS) {
return ret;
}
ret.append(s, len);
plist_mem_free(s);
return ret;
}
int main() {
int64_t v = -1;
PList::Integer i1(v);
PList::Integer i2(i1); // Copy constructor
printf("i1 xml:\n%s\n", to_xml(i1.GetPlist()).c_str());
printf("i2 xml:\n%s\n", to_xml(i2.GetPlist()).c_str());
return 0;
}
Compile and run:
clang++ -std=c++11 -lplist++-2.0 -lplist-2.0 test.cpp -o test
./test
Expected Behavior
Both i1
and i2
should produce the same XML representation:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
<plist version=\"1.0\">
<integer>-1</integer>
</plist>
Actual Behavior
i1
produces the correct XML, but i2
(the copy) produces:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
<plist version=\"1.0\">
<integer>18446744073709551615</integer>
</plist>
This happens because 18446744073709551615
is the unsigned representation of -1
in a 64-bit two's complement integer.
Root Cause
In the copy constructor for PList::Integer
, the code was using plist_set_uint_val
with GetValue()
, which converts the negative signed integer to an unsigned integer, causing the value to wrap around to a large positive number.
Fix
The fix replaces the problematic code in the copy constructor with a proper node copy:
// Before (problematic):
plist_set_uint_val(_node, i.GetValue());
// After (fixed):
plist_free(_node);
_node = plist_copy(i.GetPlist());
This ensures that all attributes of the original node, including its sign, are properly preserved in the copy.