TVML/ITMLKit edits global libxml2 state unsafely
| Originator: | Rodger.Combs | ||
| Number: | rdar://22821196 | Date Originated: | 2015-09-23 |
| Status: | Open | Resolved: | |
| Product: | tvOS SDK | Product Version: | |
| Classification: | Reproducible: | Always |
Summary:
`[IKDOMInitializer init]` calls `xmlDeregisterNodeDefault` and `xmlThrDefDeregisterNodeDefault`. This sets global handlers to be called by libxml2 when `xmlFreeDoc` and some other functions are called. `xmlThrDefDeregisterNodeDefault ` sets a global variable that is used when initializing new thread-specific global structures. `xmlDeregisterNodeDefault` is apparently meant to set the callback only in the semi-global state struct belonging the current thread, but due to what appears to be a bug in libxml2, it actually always sets the global variable instead.
The callback ITMLKit installs (`IKLibXMLNodeDeregistration`) calls `+[IKDOMNodeData jsNodeDataForNode:create:]`, which throws an Obj-C exception if the document being freed isn't one of IKMLKit's own documents. This makes it effectively impossible to use libxml2 in an application using TVMLKit without a very awkward workaround. I've had to avoid using `xmlDeregisterNodeDefault` when not on the main thread, and set the original callback back when finished to avoid interfering with TVMLKit. The workaround code is below, and currently needs to be replicated everywhere xmlFreeDoc (and possibly some other libxml2 functions) is called:
```
xmlDeregisterNodeFunc orig = 0;
if (xmlIsMainThread())
{
orig = xmlDeregisterNodeDefault(0);
}
else
{
orig = xmlGetGlobalState()->xmlDeregisterNodeDefaultValue;
xmlGetGlobalState()->xmlDeregisterNodeDefaultValue = 0;
}
xmlFreeDoc(xmlDoc_);
if (xmlIsMainThread())
xmlDeregisterNodeDefault(orig);
else
xmlGetGlobalState()->xmlDeregisterNodeDefaultValue = orig;
```
It would be preferable for ITMLKit to avoid using these callbacks, or to use them in a library-safe manner (which admittedly could be difficult due to the poor design of libxml2). This could be made easier by patching the bug in `xmlDeregisterNodeDefault`, which is caused by `#undef xmlDeregisterNodeDefaultValue` being performed before that function's contents in `libxml2/globals.c`.
Steps to Reproduce:
Attempt to use `xmlFreeDoc` in an app using TVMLKit
Expected Results:
App does not crash
Actual Results:
App crashes with Obj-C exception from surprising source
Version:
tvOS 9.0 (13T5347l)
Notes:
Configuration:
Apple TV TVOS 9.0 Simulator
Attachments:
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!