(7.2.239) bug in the XML parser: a new patch
Imported from http://bugzilla.roxen.com/bugzilla/show_bug.cgi?id=2773
Reported by @grubba
From: Reinhard Pfau <Reinhard.Pfau@gmx.de>
To: "pike@roxen.com" <pike@roxen.com>
Date: Sat, 16 Feb 2002 17:25:31 +0100
Subject: (7.2.239) bug in the XML parser: a new patch
Hi again,
I made another patch for the XML parser bug. This one should be more fool-proof now..
Since I didn't include comments, here is a little description:
Whenever an entity is parsed, then it's value is pushed on an input stack and this is parsed again. So I added another field to the structure "xmlinput" which can hold the name of a PE ("entity") (-- the value is already stored in the field "to_free"). A modified PUSH macro "PUSH_WE" stores this value; and the POP() macro is (ab)used to re-enter the entity into the "entities" mapping (;at this point, all recursive expansions are done for that entity).
So now we can parse DTD's with multiple expansions of an PE; and are (again) failsafe against illegal cyclic expansions (as long as the callback function doesn't allow them... but that's beyond the scope of the core parser..)
Here now my 2nd-try patch:
-----[Start: ]---vvv----vvv----vvv----vvv----vvv----vvv----vvv------
--- src/modules/spider/xml.c:7.2.239 Tue Feb 12 16:41:43 2002
+++ src/modules/spider/xml.c Sat Feb 16 16:58:30 2002
@@ -36,6 +36,7 @@
ptrdiff_t len;
ptrdiff_t pos;
struct pike_string *to_free;
+ struct pike_string *entity;
};
BLOCK_ALLOC(xmlinput, 64) @@ -675,7 +676,7 @@
#define POKE(X,Y) string_builder_putchar(&X,Y)
-#define PUSH(s) do { \
+#define PUSH_WE(s,e) do { \
struct xmlinput *i=alloc_xmlinput(); \
*i=data->input; \
data->input.next=i; \
@@ -683,13 +684,24 @@
data->input.datap=MKPCHARP_STR(s); \
data->input.len=(s)->len; \
copy_shared_string(data->input.to_free,s); \
+ if (e) copy_shared_string(data->input.entity,e); \
+ else data->input.entity=0; \
}while(0)
+#define PUSH(s) PUSH_WE(s,0) + #define XMLEOF() (data->input.len <= 0)
#define POP() do { \
struct xmlinput *i=data->input.next; \
IF_XMLDEBUG(fprintf(stderr,"SMEG POP\n"));\
+ if (data->input.entity) { \
+ if (data->input.to_free) { \
+ mapping_string_insert_string(THIS->entities, \
+ data->input.entity, data->input.to_free); \
+ } \
+ free_string(data->input.entity); \
+ } \
if(data->input.to_free) free_string(data->input.to_free); \
data->input=*i; \
really_free_xmlinput(i); \
@@ -1132,7 +1144,10 @@
XMLERROR("XML->__entities is not a mapping");
}else{
struct pike_string *name=0;
- ONERROR tmp3;
+ struct pike_string *full_name=0;
+ int external_entity_value=0;
+ ONERROR tmp3;
+ ONERROR tmp4;
push_constant_text("%");
SIMPLE_READNAME();
@@ -1140,6 +1155,8 @@
SET_ONERROR(tmp3, do_free_string, name);
f_add(2);
+ add_ref(full_name=sp[-1].u.string);
+ SET_ONERROR(tmp4, do_free_string, full_name);
if(PEEK(0)!=';')
XMLERROR("Missing ';' after parsed entity reference.");
READ(1);
@@ -1153,6 +1170,7 @@
do {
if(IS_ZERO(sp-1))
{
+ external_entity_value=1;
pop_stack();
push_constant_text("%");
ref_push_string(name);
@@ -1176,14 +1194,20 @@
IF_XMLDEBUG(fprintf(stderr, "ptr=%p len=%d pos=%d to_free=%p\n",
data->input.datap.ptr, data->input.len,
data->input.pos, data->input.to_free));
- PUSH(s);
+ if (external_entity_value) {
+ PUSH(s);
+ } else {
+ PUSH_WE(s,full_name);
+ }
READ(0); /* autopop empty strings */
pop_stack();
+ CALL_AND_UNSET_ONERROR(tmp4);
CALL_AND_UNSET_ONERROR(tmp3);
return 1;
}
}while(0);
+ CALL_AND_UNSET_ONERROR(tmp4);
CALL_AND_UNSET_ONERROR(tmp3);
}
return 0;
@@ -2657,6 +2681,7 @@
data.input.len=s->len;
data.input.pos=0;
data.input.to_free=0;
+ data.input.entity=0;
data.input.next=0;
data.func=sp+1-args;
data.extra_args=sp+2-args;
@@ -2750,6 +2775,7 @@
data.input.len=s->len;
data.input.pos=0;
data.input.to_free=0;
+ data.input.entity=0;
data.func=sp+1-args;
data.extra_args=sp+2-args;
data.num_extra_args=args-2;
-----[End : ]---^^^----^^^----^^^----^^^----^^^----^^^----^^^------
Greetings, Reinhard (/Mubo) [Pike newbie]
PS: to /Hubbe: better now? :-)
-- ** Reinhard Pfau mailto:Reinhard.Pfau@unix-ag.org ** (Mubo) mailto:Reinhard.Pfau@gmx.de ** http://www.home.unix-ag.org/reinhard.pfau/