If the DynArray within an XMLPrinter object carries 2 gigabytes of
data or more, XMLPrinter::CStrSize returns a truncated result. If a
program casts this back to size_t without thought, sign extension
leads to bad things(tm).
```c++
int main()
{
tinyxml2::XMLDocument doc;
doc.InsertEndChild(doc.NewDeclaration());
auto root = doc.NewElement("root");
size_t sz = 0x80000002;
auto blank = new char[sz];
memset(blank, ' ', sz);
blank[sz-1]='\0';
root->SetText(blank);
doc.InsertEndChild(root);
tinyxml2::XMLPrinter printer(nullptr);
doc.Print(&printer);
std::string_view sv{printer.CStr(), static_cast<size_t>(printer.CStrSize())};
// sv.size() is way too big, causing overflows on access
std::string dup(sv); // boom
}
```
Fixes: 2.0.2-873-geb3ab0d
The expression ``const int newAllocated = cap * 2;`` easily causes
overflow, as soon as the input is 1.0 GiB. This goes unnoticed because
release builds of tinyxml2 do not have active assertions.
The change in commit 9.0.0-20-g8fd6cc6 did not do anything useful;
the signed multiplication overflow (and thus undefined behavior)
still occurs.
Using ``int`` in this class is really archaic, because it limits the
class to a gigabyte even on 64-bit platforms.
The multiplication overflow check also needs to include sizeof(T),
otherwise you can run into unsigned multiplication overflow (defined,
but undesirable) in the memcpy() call.
testcase:
int main()
{
tinyxml2::XMLDocument doc;
doc.InsertEndChild(doc.NewDeclaration());
auto root = doc.NewElement("root");
size_t sz = 0x80000001;
auto blank = new char[sz];
memset(blank, ' ', sz);
blank[sz-1]='\0';
root->SetText(blank);
doc.InsertEndChild(root);
tinyxml2::XMLPrinter printer(nullptr);
doc.Print(&printer);
}
The commit changes the attribute setting functions in both the .cpp and .h files to use int32_t and uint32_t instead of int and unsigned for better type specificity.
Update integer parsing to use long type and unsigned parsing to use unsigned long type for better compatibility with different platforms. Alternatively, use the PRI Macros there.
alternatively use the PRI Macros there.
The commit changes the PushText functions in both the .cpp and .h files to utilize int32_t and uint32_t instead of int and unsigned for better type specificity.
Update attribute types to int32_t and uint32_t for better consistency and clarity.
Changed attribute types to int32_t and uint32_t for IntAttribute and UnsignedAttribute methods in both .cpp and .h files.
In the XMLUtil::ToStr( uint64_t v, char* buffer, int bufferSize ) function, the format specifier %llu was used with a signed long long argument. This caused a type mismatch warning. The argument has been changed to unsigned long long to match the format specifier, resolving the warning.
The format "%x" is treated as an unsigned int by the GCC compiler. Use static_cast to cast the error to an unsigned int to match the "%x" type. Additionally, replace int(error) with static_cast<int>(error) to avoid the old-style cast warning.