summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2006-07-06 05:13:22 (GMT)
committerFred Drake <fdrake@acm.org>2006-07-06 05:13:22 (GMT)
commit24a0f41d8380b3a13aef9c728394ba0c20b9cb90 (patch)
tree6ac655464a69bec07846f3eccbc70978ef2d9712
parenta4df11d9c34952ae6d98b17fb92cbb35f8880cc8 (diff)
downloadcpython-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.c2
-rw-r--r--Modules/pyexpat.c32
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;