Skip to content

Commit e260bd6

Browse files
committed
Change parser.object to be a zend_object*
+ Add failing test
1 parent d9083c1 commit e260bd6

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
Swap underlying object to call methods with xml_set_object()
3+
--EXTENSIONS--
4+
xml
5+
--FILE--
6+
<?php
7+
8+
class A {
9+
public function start_element($parser, $name, $attributes) {
10+
global $b;
11+
xml_set_object($parser, $b);
12+
echo "A::start_element($name)\n";
13+
}
14+
}
15+
16+
class B {
17+
public function start_element($parser, $name) {
18+
echo "B::start_element($name)\n";
19+
}
20+
}
21+
22+
$a = new A;
23+
$b = new B;
24+
25+
$parser = xml_parser_create();
26+
xml_set_object($parser, $a);
27+
xml_set_element_handler($parser, "start_element", null);
28+
xml_parse($parser, <<<XML
29+
<?xml version="1.0"?>
30+
<container>
31+
<child>
32+
</container>
33+
XML);
34+
35+
?>
36+
--EXPECT--
37+
A::start_element(CONTAINER)
38+
B::start_element(CHILD)

ext/xml/xml.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ typedef struct {
6969
* It is not owned, do not release it. */
7070
zval index;
7171

72-
zval object;
72+
zend_object *object;
7373
zend_fcall_info_cache startElementHandler;
7474
zend_fcall_info_cache endElementHandler;
7575
zend_fcall_info_cache characterDataHandler;
@@ -359,8 +359,8 @@ static void xml_parser_free_obj(zend_object *object)
359359
if (parser->baseURI) {
360360
efree(parser->baseURI);
361361
}
362-
if (!Z_ISUNDEF(parser->object)) {
363-
zval_ptr_dtor(&parser->object);
362+
if (parser->object) {
363+
OBJ_RELEASE(parser->object);
364364
}
365365

366366
zend_object_std_dtor(&parser->std);
@@ -371,7 +371,7 @@ static HashTable *xml_parser_get_gc(zend_object *object, zval **table, int *n)
371371
xml_parser *parser = xml_parser_from_obj(object);
372372

373373
zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create();
374-
zend_get_gc_buffer_add_zval(gc_buffer, &parser->object);
374+
zend_get_gc_buffer_add_obj(gc_buffer, parser->object);
375375
if (ZEND_FCC_INITIALIZED(parser->startElementHandler)) {
376376
zend_get_gc_buffer_add_fcc(gc_buffer, &parser->startElementHandler);
377377
}
@@ -1062,8 +1062,13 @@ PHP_FUNCTION(xml_set_object)
10621062

10631063
parser = Z_XMLPARSER_P(pind);
10641064

1065-
zval_ptr_dtor(&parser->object);
1066-
ZVAL_OBJ_COPY(&parser->object, Z_OBJ_P(mythis));
1065+
if (parser->object) {
1066+
// TODO Check methods exist in set FCCs
1067+
OBJ_RELEASE(parser->object);
1068+
}
1069+
1070+
parser->object = Z_OBJ_P(mythis);
1071+
GC_ADDREF(parser->object);
10671072

10681073
RETURN_TRUE;
10691074
}
@@ -1080,12 +1085,12 @@ static bool php_xml_check_string_method_arg(
10801085
return true;
10811086
}
10821087

1083-
if (Z_ISUNDEF(parser->object)) {
1088+
if (!parser->object) {
10841089
zend_argument_value_error(arg_num, "an object must be set via xml_set_object() to be able to lookup method");
10851090
return false;
10861091
}
10871092

1088-
zend_class_entry *ce = Z_OBJCE(parser->object);
1093+
zend_class_entry *ce = parser->object->ce;
10891094
zend_string *lc_name = zend_string_tolower(method_name);
10901095
zend_function *method_ptr = zend_hash_find_ptr(&ce->function_table, lc_name);
10911096
zend_string_release_ex(lc_name, 0);
@@ -1097,7 +1102,7 @@ static bool php_xml_check_string_method_arg(
10971102
parser_handler_fcc->function_handler = method_ptr;
10981103
parser_handler_fcc->calling_scope = ce;
10991104
parser_handler_fcc->called_scope = ce;
1100-
parser_handler_fcc->object = Z_OBJ(parser->object);
1105+
parser_handler_fcc->object = parser->object;
11011106

11021107
return true;
11031108
}

0 commit comments

Comments
 (0)