@@ -79,13 +79,13 @@ typedef struct {
79
79
zend_fcall_info_cache externalEntityRefHandler ;
80
80
zend_fcall_info_cache startNamespaceDeclHandler ;
81
81
zend_fcall_info_cache endNamespaceDeclHandler ;
82
-
83
82
zval data ;
84
83
zval info ;
84
+
85
85
int level ;
86
86
int toffset ;
87
87
int curtag ;
88
- zval * ctag ;
88
+ zend_long ctag_index ;
89
89
char * * ltags ;
90
90
bool lastwasopen ;
91
91
bool skipwhite ;
@@ -333,6 +333,8 @@ static void xml_parser_free_obj(zend_object *object)
333
333
{
334
334
xml_parser * parser = xml_parser_from_obj (object );
335
335
336
+ zval_ptr_dtor (& parser -> info );
337
+ zval_ptr_dtor (& parser -> data );
336
338
if (parser -> parser ) {
337
339
XML_ParserFree (parser -> parser );
338
340
}
@@ -425,6 +427,8 @@ static HashTable *xml_parser_get_gc(zend_object *object, zval **table, int *n)
425
427
if (ZEND_FCC_INITIALIZED (parser -> endNamespaceDeclHandler )) {
426
428
zend_get_gc_buffer_add_fcc (gc_buffer , & parser -> endNamespaceDeclHandler );
427
429
}
430
+ zend_get_gc_buffer_add_zval (gc_buffer , & parser -> data );
431
+ zend_get_gc_buffer_add_zval (gc_buffer , & parser -> info );
428
432
429
433
zend_get_gc_buffer_use (gc_buffer , table , n );
430
434
@@ -553,15 +557,18 @@ static void xml_add_to_info(xml_parser *parser, const char *name)
553
557
{
554
558
zval * element ;
555
559
556
- if (Z_ISUNDEF (parser -> info )) {
560
+ if (Z_ISUNDEF (parser -> info ) || UNEXPECTED ( Z_TYPE_P ( Z_REFVAL ( parser -> info )) != IS_ARRAY ) ) {
557
561
return ;
558
562
}
559
563
564
+ SEPARATE_ARRAY (Z_REFVAL (parser -> info ));
565
+ zend_array * arr = Z_ARRVAL_P (Z_REFVAL (parser -> info ));
566
+
560
567
size_t name_len = strlen (name );
561
- if ((element = zend_hash_str_find (Z_ARRVAL ( parser -> info ) , name , name_len )) == NULL ) {
568
+ if ((element = zend_hash_str_find (arr , name , name_len )) == NULL ) {
562
569
zval values ;
563
570
array_init (& values );
564
- element = zend_hash_str_update (Z_ARRVAL ( parser -> info ) , name , name_len , & values );
571
+ element = zend_hash_str_update (arr , name , name_len , & values );
565
572
}
566
573
567
574
add_next_index_long (element , parser -> curtag );
@@ -585,6 +592,28 @@ static zend_string *xml_decode_tag(xml_parser *parser, const XML_Char *tag)
585
592
}
586
593
/* }}} */
587
594
595
+ static zval * xml_get_separated_data (xml_parser * parser )
596
+ {
597
+ if (EXPECTED (Z_TYPE_P (Z_REFVAL (parser -> data )) == IS_ARRAY )) {
598
+ SEPARATE_ARRAY (Z_REFVAL (parser -> data ));
599
+ return Z_REFVAL (parser -> data );
600
+ }
601
+ return NULL ;
602
+ }
603
+
604
+ static zval * xml_get_ctag (xml_parser * parser )
605
+ {
606
+ zval * data = xml_get_separated_data (parser );
607
+ if (EXPECTED (data )) {
608
+ zval * zv = zend_hash_index_find_deref (Z_ARRVAL_P (data ), parser -> ctag_index );
609
+ if (EXPECTED (zv && Z_TYPE_P (zv ) == IS_ARRAY )) {
610
+ SEPARATE_ARRAY (zv );
611
+ return zv ;
612
+ }
613
+ }
614
+ return NULL ;
615
+ }
616
+
588
617
/* {{{ xml_startElementHandler() */
589
618
void xml_startElementHandler (void * userData , const XML_Char * name , const XML_Char * * attributes )
590
619
{
@@ -666,7 +695,19 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha
666
695
zval_ptr_dtor (& atr );
667
696
}
668
697
669
- parser -> ctag = zend_hash_next_index_insert (Z_ARRVAL (parser -> data ), & tag );
698
+ zval * data = xml_get_separated_data (parser );
699
+ if (EXPECTED (data )) {
700
+ /* Note: due to array resizes or user interference,
701
+ * we have to store an index instead of a zval into the array's memory. */
702
+ zend_array * arr = Z_ARRVAL_P (data );
703
+ if (EXPECTED (zend_hash_next_index_insert (arr , & tag ))) {
704
+ parser -> ctag_index = arr -> nNextFreeElement - 1 ;
705
+ } else {
706
+ zval_ptr_dtor (& tag );
707
+ }
708
+ } else {
709
+ zval_ptr_dtor (& tag );
710
+ }
670
711
} else if (parser -> level == (XML_MAXLEVEL + 1 )) {
671
712
php_error_docref (NULL , E_WARNING , "Maximum depth exceeded - Results truncated" );
672
713
}
@@ -701,17 +742,21 @@ void xml_endElementHandler(void *userData, const XML_Char *name)
701
742
zval tag ;
702
743
703
744
if (parser -> lastwasopen ) {
704
- add_assoc_string (parser -> ctag , "type" , "complete" );
745
+ zval * zv = xml_get_ctag (parser );
746
+ if (EXPECTED (zv )) {
747
+ add_assoc_string (zv , "type" , "complete" );
748
+ }
705
749
} else {
706
- array_init (& tag );
707
-
708
750
xml_add_to_info (parser , ZSTR_VAL (tag_name ) + parser -> toffset );
709
751
710
- add_assoc_string (& tag , "tag" , SKIP_TAGSTART (ZSTR_VAL (tag_name ))); /* cast to avoid gcc-warning */
711
- add_assoc_string (& tag , "type" , "close" );
712
- add_assoc_long (& tag , "level" , parser -> level );
713
-
714
- zend_hash_next_index_insert (Z_ARRVAL (parser -> data ), & tag );
752
+ zval * data = xml_get_separated_data (parser );
753
+ if (EXPECTED (data )) {
754
+ array_init (& tag );
755
+ add_assoc_string (& tag , "tag" , SKIP_TAGSTART (ZSTR_VAL (tag_name ))); /* cast to avoid gcc-warning */
756
+ add_assoc_string (& tag , "type" , "close" );
757
+ add_assoc_long (& tag , "level" , parser -> level );
758
+ zend_hash_next_index_insert (Z_ARRVAL_P (data ), & tag );
759
+ }
715
760
}
716
761
717
762
parser -> lastwasopen = 0 ;
@@ -770,27 +815,41 @@ void xml_characterDataHandler(void *userData, const XML_Char *s, int len)
770
815
}
771
816
}
772
817
if (parser -> lastwasopen ) {
818
+ zval * ctag = xml_get_ctag (parser );
819
+ if (UNEXPECTED (!ctag )) {
820
+ zend_string_release_ex (decoded_value , false);
821
+ return ;
822
+ }
823
+
773
824
zval * myval ;
774
825
/* check if the current tag already has a value - if yes append to that! */
775
- if ((myval = zend_hash_find (Z_ARRVAL_P (parser -> ctag ), ZSTR_KNOWN (ZEND_STR_VALUE )))) {
826
+ if ((myval = zend_hash_find (Z_ARRVAL_P (ctag ), ZSTR_KNOWN (ZEND_STR_VALUE ))) && Z_TYPE_P ( myval ) == IS_STRING ) {
776
827
size_t newlen = Z_STRLEN_P (myval ) + ZSTR_LEN (decoded_value );
777
828
Z_STR_P (myval ) = zend_string_extend (Z_STR_P (myval ), newlen , 0 );
778
829
strncpy (Z_STRVAL_P (myval ) + Z_STRLEN_P (myval ) - ZSTR_LEN (decoded_value ),
779
830
ZSTR_VAL (decoded_value ), ZSTR_LEN (decoded_value ) + 1 );
780
831
zend_string_release_ex (decoded_value , 0 );
781
832
} else {
782
833
if (doprint || (! parser -> skipwhite )) {
783
- add_assoc_str (parser -> ctag , "value" , decoded_value );
834
+ add_assoc_str (ctag , "value" , decoded_value );
784
835
} else {
785
836
zend_string_release_ex (decoded_value , 0 );
786
837
}
787
838
}
788
839
} else {
789
840
zval tag ;
790
841
zval * curtag , * mytype , * myval ;
791
- ZEND_HASH_REVERSE_FOREACH_VAL (Z_ARRVAL (parser -> data ), curtag ) {
792
- if ((mytype = zend_hash_str_find (Z_ARRVAL_P (curtag ),"type" , sizeof ("type" ) - 1 ))) {
793
- if (zend_string_equals_literal (Z_STR_P (mytype ), "cdata" )) {
842
+
843
+ zval * data = xml_get_separated_data (parser );
844
+ if (UNEXPECTED (!data )) {
845
+ zend_string_release_ex (decoded_value , false);
846
+ return ;
847
+ }
848
+
849
+ ZEND_HASH_REVERSE_FOREACH_VAL (Z_ARRVAL_P (data ), curtag ) {
850
+ if (EXPECTED (Z_TYPE_P (curtag ) == IS_ARRAY ) && (mytype = zend_hash_str_find (Z_ARRVAL_P (curtag ),"type" , sizeof ("type" ) - 1 ))) {
851
+ if (EXPECTED (Z_TYPE_P (mytype ) == IS_STRING ) && zend_string_equals_literal (Z_STR_P (mytype ), "cdata" )) {
852
+ SEPARATE_ARRAY (curtag );
794
853
if ((myval = zend_hash_find (Z_ARRVAL_P (curtag ), ZSTR_KNOWN (ZEND_STR_VALUE )))) {
795
854
size_t newlen = Z_STRLEN_P (myval ) + ZSTR_LEN (decoded_value );
796
855
Z_STR_P (myval ) = zend_string_extend (Z_STR_P (myval ), newlen , 0 );
@@ -810,7 +869,7 @@ void xml_characterDataHandler(void *userData, const XML_Char *s, int len)
810
869
add_assoc_str (& tag , "value" , decoded_value );
811
870
add_assoc_string (& tag , "type" , "cdata" );
812
871
add_assoc_long (& tag , "level" , parser -> level );
813
- zend_hash_next_index_insert (Z_ARRVAL ( parser -> data ), & tag );
872
+ zend_hash_next_index_insert (Z_ARRVAL_P ( data ), & tag );
814
873
} else if (parser -> level == (XML_MAXLEVEL + 1 )) {
815
874
php_error_docref (NULL , E_WARNING , "Maximum depth exceeded - Results truncated" );
816
875
} else {
@@ -1366,21 +1425,21 @@ PHP_FUNCTION(xml_parse_into_struct)
1366
1425
}
1367
1426
1368
1427
if (info ) {
1369
- info = zend_try_array_init (info );
1370
- if (!info ) {
1428
+ if (!zend_try_array_init (info )) {
1371
1429
RETURN_THROWS ();
1372
1430
}
1373
1431
}
1374
1432
1375
- xdata = zend_try_array_init (xdata );
1376
- if (!xdata ) {
1433
+ if (!zend_try_array_init (xdata )) {
1377
1434
RETURN_THROWS ();
1378
1435
}
1379
1436
1380
- ZVAL_COPY_VALUE (& parser -> data , xdata );
1437
+ zval_ptr_dtor (& parser -> data );
1438
+ ZVAL_COPY (& parser -> data , xdata );
1381
1439
1382
1440
if (info ) {
1383
- ZVAL_COPY_VALUE (& parser -> info , info );
1441
+ zval_ptr_dtor (& parser -> info );
1442
+ ZVAL_COPY (& parser -> info , info );
1384
1443
}
1385
1444
1386
1445
parser -> level = 0 ;
0 commit comments