diff options
author | Fred Drake <fdrake@acm.org> | 2006-07-06 05:13:22 (GMT) |
---|---|---|
committer | Fred Drake <fdrake@acm.org> | 2006-07-06 05:13:22 (GMT) |
commit | 24a0f41d8380b3a13aef9c728394ba0c20b9cb90 (patch) | |
tree | 6ac655464a69bec07846f3eccbc70978ef2d9712 | |
parent | a4df11d9c34952ae6d98b17fb92cbb35f8880cc8 (diff) | |
download | cpython-24a0f41d8380b3a13aef9c728394ba0c20b9cb90.zip cpython-24a0f41d8380b3a13aef9c728394ba0c20b9cb90.tar.gz cpython-24a0f41d8380b3a13aef9c728394ba0c20b9cb90.tar.bz2 |
- 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)
-rw-r--r-- | Modules/expat/xmlparse.c | 2 | ||||
-rw-r--r-- | 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; |