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!