Skip to content

XMLParser fixes (SR-13546, SR-2301) #2920

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 102 additions & 20 deletions CoreFoundation/Parsing.subproj/CFXMLInterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,27 @@ typedef struct {
xmlNotationPtr notation;
} _cfxmlNotation;

// I'm not sure if libxml handles external entities as it should do.
// This struct is used to handle callback calls that happen during
// an external entity is loaded.
struct CFXMLInterfacePrivateState {
// If this field is not 0, some delegate calls are blocked.
uint8_t delegateBlocked;

// Flag set when the get entity call is seen.
uint8_t gettingEntity;
// parsing depth while getting an entity.
uint32_t depth;
};


#if DEPLOYMENT_RUNTIME_SWIFT
static xmlExternalEntityLoader __originalLoader = NULL;

static xmlParserInputPtr _xmlExternalEntityLoader(const char *urlStr, const char * ID, xmlParserCtxtPtr context) {
_CFXMLInterface parser = __CFSwiftXMLParserBridge.currentParser();
if (parser != NULL) {
return __CFSwiftXMLParserBridge._xmlExternalEntityWithURL(parser, urlStr, ID, context, __originalLoader);
return __CFSwiftXMLParserBridge._xmlExternalEntityWithURL(parser, (const unsigned char *)urlStr, (const unsigned char *)ID, context, (_CFXMLInterfaceExternalEntityLoader) __originalLoader);
}
return __originalLoader(urlStr, ID, context);
}
Expand All @@ -154,8 +168,8 @@ void _CFSetupXMLBridgeIfNeededUsingBlock(void (^block)(void)) {
#endif // DEPLOYMENT_RUNTIME_SWIFT
}

_CFXMLInterfaceParserInput _CFXMLInterfaceNoNetExternalEntityLoader(const char *URL, const char *ID, _CFXMLInterfaceParserContext ctxt) {
return xmlNoNetExternalEntityLoader(URL, ID, ctxt);
_CFXMLInterfaceParserInput _CFXMLInterfaceNoNetExternalEntityLoader(const unsigned char *URL, const unsigned char *ID, _CFXMLInterfaceParserContext ctxt) {
return xmlNoNetExternalEntityLoader((const char *) URL, (const char *) ID, ctxt);
}

#if DEPLOYMENT_RUNTIME_SWIFT
Expand All @@ -170,31 +184,41 @@ static void _errorCallback(void *ctx, const char *msg, ...) {
_CFXMLInterfaceSAXHandler _CFXMLInterfaceCreateSAXHandler() {
_CFXMLInterfaceSAXHandler saxHandler = (_CFXMLInterfaceSAXHandler)calloc(1, sizeof(struct _xmlSAXHandler));
#if DEPLOYMENT_RUNTIME_SWIFT
// To make it easier to spot missing or unused callbacks, the order of setting follows
// that of _xmlSAXHandler with unused (or outdated) callbacks being commented out.

saxHandler->internalSubset = (internalSubsetSAXFunc)__CFSwiftXMLParserBridge.internalSubset;
saxHandler->isStandalone = (isStandaloneSAXFunc)__CFSwiftXMLParserBridge.isStandalone;

saxHandler->hasInternalSubset = (hasInternalSubsetSAXFunc)__CFSwiftXMLParserBridge.hasInternalSubset;
saxHandler->hasExternalSubset = (hasExternalSubsetSAXFunc)__CFSwiftXMLParserBridge.hasExternalSubset;

// saxHandler->resolveEntity replaced by xmlSetExternalEntityLoader
saxHandler->getEntity = (getEntitySAXFunc)__CFSwiftXMLParserBridge.getEntity;

saxHandler->entityDecl = (entityDeclSAXFunc)__CFSwiftXMLParserBridge.entityDecl;
saxHandler->notationDecl = (notationDeclSAXFunc)__CFSwiftXMLParserBridge.notationDecl;
saxHandler->attributeDecl = (attributeDeclSAXFunc)__CFSwiftXMLParserBridge.attributeDecl;
saxHandler->elementDecl = (elementDeclSAXFunc)__CFSwiftXMLParserBridge.elementDecl;
saxHandler->unparsedEntityDecl = (unparsedEntityDeclSAXFunc)__CFSwiftXMLParserBridge.unparsedEntityDecl;
// saxHandler->setDocumentLocator currently not used by CFXMLInterface
saxHandler->startDocument = (startDocumentSAXFunc)__CFSwiftXMLParserBridge.startDocument;
saxHandler->endDocument = (endDocumentSAXFunc)__CFSwiftXMLParserBridge.endDocument;
saxHandler->startElementNs = (startElementNsSAX2Func)__CFSwiftXMLParserBridge.startElementNs;
saxHandler->endElementNs = (endElementNsSAX2Func)__CFSwiftXMLParserBridge.endElementNs;
// saxHandler->startElement replaced by startElementNs
// saxHandler->endElement replaced by endElementNs
// saxHandler->reference currently not used by CFXMLInterface
saxHandler->characters = (charactersSAXFunc)__CFSwiftXMLParserBridge.characters;
saxHandler->ignorableWhitespace = (ignorableWhitespaceSAXFunc)__CFSwiftXMLParserBridge.ignorableWhitespace;
saxHandler->processingInstruction = (processingInstructionSAXFunc)__CFSwiftXMLParserBridge.processingInstruction;
saxHandler->comment = (commentSAXFunc)__CFSwiftXMLParserBridge.comment;
// saxHandler->warning currently not used by CFXMLInterface
saxHandler->error = _errorCallback;
// saxHandler->fatalError unused by libxml
// saxHandler->getParameterEntity currently not used by CFXMLInterface
saxHandler->cdataBlock = (cdataBlockSAXFunc)__CFSwiftXMLParserBridge.cdataBlock;
saxHandler->comment = (commentSAXFunc)__CFSwiftXMLParserBridge.comment;

saxHandler->externalSubset = (externalSubsetSAXFunc)__CFSwiftXMLParserBridge.externalSubset;

saxHandler->initialized = XML_SAX2_MAGIC; // make sure start/endElementNS are used
// saxHandler->_private We do not touch private parts (currently not used by CFXMLInterface).
saxHandler->startElementNs = (startElementNsSAX2Func)__CFSwiftXMLParserBridge.startElementNs;
saxHandler->endElementNs = (endElementNsSAX2Func)__CFSwiftXMLParserBridge.endElementNs;
// saxHandler->serror currently not used by CFXMLInterface
#endif //if DEPLOYMENT_RUNTIME_SWIFT
return saxHandler;
}
Expand Down Expand Up @@ -229,6 +253,9 @@ void _CFXMLInterfaceDestroyContext(_CFXMLInterfaceParserContext ctx) {
if (ctx->myDoc) {
xmlFreeDoc(ctx->myDoc);
}
if (ctx->_private) {
free(ctx->_private);
}
xmlFreeParserCtxt(ctx);
}

Expand All @@ -243,9 +270,9 @@ int _CFXMLInterfaceSAX2GetColumnNumber(_CFXMLInterfaceParserContext ctx) {
}

void _CFXMLInterfaceSAX2InternalSubset(_CFXMLInterfaceParserContext ctx,
const unsigned char *name,
const unsigned char *ExternalID,
const unsigned char *SystemID) {
const unsigned char *_Nullable name,
const unsigned char *_Nullable ExternalID,
const unsigned char *_Nullable SystemID) {
if (ctx != NULL) xmlSAX2InternalSubset(ctx, name, ExternalID, SystemID);
}

Expand Down Expand Up @@ -322,18 +349,73 @@ _CFXMLDTDNodePtr _Nullable _CFXMLDTDNewAttributeDesc(_CFXMLDTDPtr dtd, const uns
_CFXMLInterfaceEntity _CFXMLInterfaceSAX2GetEntity(_CFXMLInterfaceParserContext ctx, const unsigned char *name) {
if (ctx == NULL) return NULL;
_CFXMLInterfaceEntity entity = xmlSAX2GetEntity(ctx, name);
if (entity && ctx->instate == XML_PARSER_CONTENT) ctx->_private = (void *)1;
return entity;
}

int _CFXMLInterfaceInRecursiveState(_CFXMLInterfaceParserContext ctx) {
return ctx->_private == (void *)1;
void _CFXMLInterfacePrivateStateSetGettingEntity(_CFXMLInterfaceParserContext ctx) {
if (!ctx) return;

xmlParserCtxtPtr context = __CFSwiftXMLParserBridge.getContext((_CFXMLInterface)ctx);
if (!context->_private) {
context->_private = calloc(1, sizeof(struct CFXMLInterfacePrivateState));
}
struct CFXMLInterfacePrivateState *privateState = (struct CFXMLInterfacePrivateState *) context->_private;
privateState->gettingEntity = 1;
}

void _CFXMLInterfacePrivateStateClearGettingEntity(_CFXMLInterfaceParserContext ctx) {
if (!ctx) return;

xmlParserCtxtPtr context = __CFSwiftXMLParserBridge.getContext((_CFXMLInterface)ctx);
if (!context->_private) return;

struct CFXMLInterfacePrivateState *privateState = (struct CFXMLInterfacePrivateState *) context->_private;
privateState->gettingEntity = 0;
}

uint8_t _CFXMLInterfacePrivateStateIsGettingEntity(_CFXMLInterfaceParserContext ctx) {
if (!ctx) return 0;

xmlParserCtxtPtr context = __CFSwiftXMLParserBridge.getContext((_CFXMLInterface)ctx);
if (!context->_private) return 0;

struct CFXMLInterfacePrivateState *privateState = (struct CFXMLInterfacePrivateState *) context->_private;
return privateState->gettingEntity;
}

void _CFXMLInterfacePrivateStateModifyLevel(_CFXMLInterfaceParserContext ctx, int8_t change) {
if (!ctx) return;
xmlParserCtxtPtr context = __CFSwiftXMLParserBridge.getContext((_CFXMLInterface)ctx);
if (!context->_private) {
context->_private = calloc(1, sizeof(struct CFXMLInterfacePrivateState));
}

struct CFXMLInterfacePrivateState *privateState = (struct CFXMLInterfacePrivateState *) context->_private;

if (0 == change && !privateState->gettingEntity) {
privateState->depth = 0;
privateState->delegateBlocked = 1;
} else if (0 < change && privateState->delegateBlocked != 0) {
privateState->depth++;
} else if (0 > change && privateState->delegateBlocked != 0 && 0 < privateState->depth) {
privateState->depth--;
if (0 == privateState->depth) {
privateState->delegateBlocked = 0;
}
}
}

void _CFXMLInterfaceResetRecursiveState(_CFXMLInterfaceParserContext ctx) {
ctx->_private = NULL;
uint8_t _CFXMLInterfacePrivateStateDelegateCallsBlocked(_CFXMLInterfaceParserContext ctx) {
if (!ctx) return 0;

xmlParserCtxtPtr context = __CFSwiftXMLParserBridge.getContext((_CFXMLInterface)ctx);
if (!context->_private) return 0;

struct CFXMLInterfacePrivateState *privateState = (struct CFXMLInterfacePrivateState *) context->_private;
return privateState->delegateBlocked;
}


int _CFXMLInterfaceHasDocument(_CFXMLInterfaceParserContext ctx) {
if (ctx == NULL) return 0;
return ctx->myDoc != NULL;
Expand Down Expand Up @@ -749,7 +831,7 @@ CFStringRef _CFXMLDocCopyCharacterEncoding(_CFXMLDocPtr doc) {
return __CFSwiftXMLParserBridgeCF.CFStringCreateWithCString(NULL, (const char*)((xmlDocPtr)doc)->encoding, kCFStringEncodingUTF8);
}

void _CFXMLDocSetCharacterEncoding(_CFXMLDocPtr doc, const unsigned char* _Nullable encoding) {
void _CFXMLDocSetCharacterEncoding(_CFXMLDocPtr doc, const unsigned char* _Nullable encoding) {
xmlDocPtr docPtr = (xmlDocPtr)doc;

if (docPtr->encoding) {
Expand Down
52 changes: 35 additions & 17 deletions CoreFoundation/Parsing.subproj/CFXMLInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,13 @@ typedef struct _xmlElementContent *_CFXMLInterfaceElementContent;
typedef struct _xmlError *_CFXMLInterfaceError;
typedef struct __CFXMLInterface *_CFXMLInterface;

typedef _CFXMLInterfaceParserInput _Nonnull (*_CFXMLInterfaceExternalEntityLoader)(const char *URL, const char *ID, _CFXMLInterfaceParserContext);
typedef _CFXMLInterfaceParserInput _Nonnull (*_CFXMLInterfaceExternalEntityLoader)(const unsigned char *URL, const unsigned char *ID, _CFXMLInterfaceParserContext);
typedef void (*_CFXMLInterfaceStructuredErrorFunc)(_CFXMLInterface ctx, _CFXMLInterfaceError error);

void _CFSetupXMLInterface(void);
void _CFSetupXMLBridgeIfNeededUsingBlock(void (^block)(void));

_CFXMLInterfaceParserInput _CFXMLInterfaceNoNetExternalEntityLoader(const char *URL, const char *ID, _CFXMLInterfaceParserContext ctxt);
_CFXMLInterfaceParserInput _CFXMLInterfaceNoNetExternalEntityLoader(const unsigned char *URL, const unsigned char *ID, _CFXMLInterfaceParserContext ctxt);
_CFXMLInterfaceSAXHandler _CFXMLInterfaceCreateSAXHandler(void);
void _CFXMLInterfaceDestroySAXHandler(_CFXMLInterfaceSAXHandler handler);
void _CFXMLInterfaceSetStructuredErrorFunc(_CFXMLInterface ctx, _CFXMLInterfaceStructuredErrorFunc _Nullable handler);
Expand All @@ -115,9 +115,9 @@ void _CFXMLInterfaceDestroyContext(_CFXMLInterfaceParserContext _Nullable ctx);
int _CFXMLInterfaceSAX2GetColumnNumber(_CFXMLInterfaceParserContext _Nullable ctx);
int _CFXMLInterfaceSAX2GetLineNumber(_CFXMLInterfaceParserContext _Nullable ctx);
void _CFXMLInterfaceSAX2InternalSubset(_CFXMLInterfaceParserContext _Nullable ctx,
const unsigned char * name,
const unsigned char * ExternalID,
const unsigned char * SystemID);
const unsigned char *_Nullable name,
const unsigned char *_Nullable ExternalID,
const unsigned char *_Nullable SystemID);
void _CFXMLInterfaceSAX2ExternalSubset(_CFXMLInterfaceParserContext _Nullable ctx,
const unsigned char * name,
const unsigned char * ExternalID,
Expand All @@ -127,13 +127,18 @@ int _CFXMLInterfaceHasInternalSubset(_CFXMLInterfaceParserContext _Nullable ctx)
int _CFXMLInterfaceHasExternalSubset(_CFXMLInterfaceParserContext _Nullable ctx);
_CFXMLInterfaceEntity _Nullable _CFXMLInterfaceGetPredefinedEntity(const unsigned char * name);
_CFXMLInterfaceEntity _Nullable _CFXMLInterfaceSAX2GetEntity(_CFXMLInterfaceParserContext _Nullable ctx, const unsigned char * name);
int _CFXMLInterfaceInRecursiveState(_CFXMLInterfaceParserContext ctx);
void _CFXMLInterfaceResetRecursiveState(_CFXMLInterfaceParserContext ctx);
int _CFXMLInterfaceHasDocument(_CFXMLInterfaceParserContext _Nullable ctx);
void _CFXMLInterfaceFreeEnumeration(_CFXMLInterfaceEnumeration _Nullable enumeration);
void _CFXMLInterfaceSAX2UnparsedEntityDecl(_CFXMLInterfaceParserContext _Nullable ctx, const unsigned char * name, const unsigned char *_Nullable publicId, const unsigned char *_Nullable systemId, const unsigned char *_Nullable notationName);
CFErrorRef _CFErrorCreateFromXMLInterface(_CFXMLInterfaceError err) CF_RETURNS_RETAINED;

void _CFXMLInterfacePrivateStateSetGettingEntity(_CFXMLInterfaceParserContext ctx);
void _CFXMLInterfacePrivateStateClearGettingEntity(_CFXMLInterfaceParserContext ctx);
uint8_t _CFXMLInterfacePrivateStateIsGettingEntity(_CFXMLInterfaceParserContext ctx);
void _CFXMLInterfacePrivateStateModifyLevel(_CFXMLInterfaceParserContext ctx, int8_t change);
uint8_t _CFXMLInterfacePrivateStateDelegateCallsBlocked(_CFXMLInterfaceParserContext ctx);


typedef void* _CFXMLNodePtr;
typedef void* _CFXMLDocPtr;
typedef void* _CFXMLNamespacePtr;
Expand Down Expand Up @@ -265,35 +270,45 @@ struct _NSXMLParserBridge {
void *CFBridge;

_CFXMLInterface _Nullable (*_Nonnull currentParser)(void);
_CFXMLInterfaceParserInput _Nullable (*_Nonnull _xmlExternalEntityWithURL)(_CFXMLInterface /*interface*/, const char * /*url*/, const char * /*identifier*/, _CFXMLInterfaceParserContext /*context*/, _CFXMLInterfaceExternalEntityLoader /*originalLoaderFunction*/);
_CFXMLInterfaceParserInput _Nullable (*_Nonnull _xmlExternalEntityWithURL)(_CFXMLInterface /*interface*/, const unsigned char * /*url*/, const unsigned char * /*identifier*/, _CFXMLInterfaceParserContext /*context*/, _CFXMLInterfaceExternalEntityLoader /*originalLoaderFunction*/);

_CFXMLInterfaceParserContext _Nonnull (*_Nonnull getContext)(_CFXMLInterface ctx);

void (*internalSubset)(_CFXMLInterface ctx, const unsigned char *name, const unsigned char *ExternalID, const unsigned char *SystemID);
void (*internalSubset)(_CFXMLInterface ctx,
const unsigned char *_Nullable name,
const unsigned char *_Nullable ExternalID,
const unsigned char *_Nullable SystemID);
int (*isStandalone)(_CFXMLInterface ctx);
int (*hasInternalSubset)(_CFXMLInterface ctx);
int (*hasExternalSubset)(_CFXMLInterface ctx);
_CFXMLInterfaceEntity _Nullable (*_Nonnull getEntity)(_CFXMLInterface ctx, const unsigned char *name);
_CFXMLInterfaceEntity _Nullable (*_Nonnull getEntity)(_CFXMLInterface ctx,
const unsigned char *name);
void (*entityDecl)(_CFXMLInterface ctx,
const unsigned char *name,
int type,
const unsigned char *_Nullable publicId,
const unsigned char *_Nullable systemId,
unsigned char *_Nullable content);
void (*notationDecl)(_CFXMLInterface ctx,
const unsigned char *name,
const unsigned char *publicId,
const unsigned char *systemId);
const unsigned char *_Nullable publicId,
const unsigned char *_Nullable systemId);
void (*attributeDecl)(_CFXMLInterface ctx,
const unsigned char *elem,
const unsigned char *fullname,
int type,
int def,
const unsigned char *defaultValue,
const unsigned char *_Nullable defaultValue,
_CFXMLInterfaceEnumeration tree);
void (*elementDecl)(_CFXMLInterface ctx,
const unsigned char *name,
int type,
_CFXMLInterfaceElementContent content);
void (*unparsedEntityDecl)(_CFXMLInterface ctx,
const unsigned char *name,
const unsigned char *publicId,
const unsigned char *systemId,
const unsigned char *notationName);
const unsigned char *_Nullable publicId,
const unsigned char *_Nullable systemId,
const unsigned char *_Nullable notationName);
void (*startDocument)(_CFXMLInterface ctx);
void (*endDocument)(_CFXMLInterface ctx);
void (*startElementNs)(_CFXMLInterface ctx,
Expand All @@ -312,9 +327,12 @@ struct _NSXMLParserBridge {
void (*characters)(_CFXMLInterface ctx,
const unsigned char *ch,
int len);
void (*ignorableWhitespace)(_CFXMLInterface ctx,
const unsigned char *ch,
int len);
void (*processingInstruction)(_CFXMLInterface ctx,
const unsigned char *target,
const unsigned char *data);
const unsigned char *_Nullable data);
void (*cdataBlock)(_CFXMLInterface ctx,
const unsigned char *value,
int len);
Expand Down
Loading