From 24a0f41d8380b3a13aef9c728394ba0c20b9cb90 Mon Sep 17 00:00:00 2001 From: Fred Drake Date: Thu, 6 Jul 2006 05:13:22 +0000 Subject: - back out Expat change; the final fix to Expat will be different - change the pyexpat wrapper to not be so sensitive to this detail of the Expat implementation (the ex-crasher test still passes) --- Modules/expat/xmlparse.c | 2 -- Modules/pyexpat.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/Modules/expat/xmlparse.c b/Modules/expat/xmlparse.c index f8fc027..882470d 100644 --- a/Modules/expat/xmlparse.c +++ b/Modules/expat/xmlparse.c @@ -2552,8 +2552,6 @@ doContent(XML_Parser parser, (int)(dataPtr - (ICHAR *)dataBuf)); if (s == next) break; - if (ps_parsing == XML_FINISHED || ps_parsing == XML_SUSPENDED) - break; *eventPP = s; } } diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index 8a10bab..67f7007 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -238,6 +238,18 @@ error_external_entity_ref_handler(XML_Parser parser, return 0; } +/* Dummy character data handler used when an error (exception) has + been detected, and the actual parsing can be terminated early. + This is needed since character data handler can't be safely removed + from within the character data handler, but can be replaced. It is + used only from the character data handler trampoline, and must be + used right after `flag_error()` is called. */ +static void +noop_character_data_handler(void *userData, const XML_Char *data, int len) +{ + /* Do nothing. */ +} + static void flag_error(xmlparseobject *self) { @@ -457,6 +469,8 @@ call_character_handler(xmlparseobject *self, const XML_Char *buffer, int len) if (temp == NULL) { Py_DECREF(args); flag_error(self); + XML_SetCharacterDataHandler(self->itself, + noop_character_data_handler); return -1; } PyTuple_SET_ITEM(args, 0, temp); @@ -469,6 +483,8 @@ call_character_handler(xmlparseobject *self, const XML_Char *buffer, int len) Py_DECREF(args); if (temp == NULL) { flag_error(self); + XML_SetCharacterDataHandler(self->itself, + noop_character_data_handler); return -1; } Py_DECREF(temp); @@ -1542,8 +1558,22 @@ sethandler(xmlparseobject *self, const char *name, PyObject* v) xmlhandler c_handler = NULL; PyObject *temp = self->handlers[handlernum]; - if (v == Py_None) + if (v == Py_None) { + /* If this is the character data handler, and a character + data handler is already active, we need to be more + careful. What we can safely do is replace the existing + character data handler callback function with a no-op + function that will refuse to call Python. The downside + is that this doesn't completely remove the character + data handler from the C layer if there's any callback + active, so Expat does a little more work than it + otherwise would, but that's really an odd case. A more + elaborate system of handlers and state could remove the + C handler more effectively. */ + if (handlernum == CharacterData && self->in_callback) + c_handler = noop_character_data_handler; v = NULL; + } else if (v != NULL) { Py_INCREF(v); c_handler = handler_info[handlernum].handler; -- cgit v0.12