@@ -86,7 +86,7 @@ typedef struct {
86
86
int toffset ;
87
87
int curtag ;
88
88
zend_long ctag_index ;
89
- char * * ltags ;
89
+ zend_string * * ltags ;
90
90
bool lastwasopen ;
91
91
bool skipwhite ;
92
92
bool isparsing ;
@@ -116,8 +116,6 @@ ZEND_GET_MODULE(xml)
116
116
117
117
#define XML_MAXLEVEL 255 /* XXX this should be dynamic */
118
118
119
- #define SKIP_TAGSTART (str ) ((str) + (parser->toffset > strlen(str) ? strlen(str) : parser->toffset))
120
-
121
119
static zend_class_entry * xml_parser_ce ;
122
120
static zend_object_handlers xml_parser_object_handlers ;
123
121
@@ -138,7 +136,7 @@ inline static unsigned short xml_encode_us_ascii(unsigned char);
138
136
inline static char xml_decode_us_ascii (unsigned short );
139
137
static void xml_xmlchar_zval (const XML_Char * , int , const XML_Char * , zval * );
140
138
static int xml_xmlcharlen (const XML_Char * );
141
- static void xml_add_to_info (xml_parser * parser , const char * name );
139
+ static void xml_add_to_info (xml_parser * parser , zend_string * name );
142
140
inline static zend_string * xml_decode_tag (xml_parser * parser , const XML_Char * tag );
143
141
144
142
void xml_startElementHandler (void * , const XML_Char * , const XML_Char * * );
@@ -311,7 +309,6 @@ static inline xml_parser *xml_parser_from_obj(zend_object *obj) {
311
309
312
310
static zend_object * xml_parser_create_object (zend_class_entry * class_type ) {
313
311
xml_parser * intern = zend_object_alloc (sizeof (xml_parser ), class_type );
314
- memset (intern , 0 , sizeof (xml_parser ) - sizeof (zend_object ));
315
312
316
313
zend_object_std_init (& intern -> std , class_type );
317
314
object_properties_init (& intern -> std , class_type );
@@ -323,8 +320,11 @@ static void xml_parser_free_ltags(xml_parser *parser)
323
320
{
324
321
if (parser -> ltags ) {
325
322
int inx ;
326
- for (inx = 0 ; ((inx < parser -> level ) && (inx < XML_MAXLEVEL )); inx ++ )
327
- efree (parser -> ltags [ inx ]);
323
+ for (inx = 0 ; ((inx < parser -> level ) && (inx < XML_MAXLEVEL )); inx ++ ) {
324
+ if (parser -> ltags [inx ]) {
325
+ zend_string_release_ex (parser -> ltags [inx ], false);
326
+ }
327
+ }
328
328
efree (parser -> ltags );
329
329
}
330
330
}
@@ -553,7 +553,7 @@ static int xml_xmlcharlen(const XML_Char *s)
553
553
/* }}} */
554
554
555
555
/* {{{ xml_add_to_info() */
556
- static void xml_add_to_info (xml_parser * parser , const char * name )
556
+ static void xml_add_to_info (xml_parser * parser , zend_string * name )
557
557
{
558
558
zval * element ;
559
559
@@ -564,11 +564,10 @@ static void xml_add_to_info(xml_parser *parser, const char *name)
564
564
SEPARATE_ARRAY (Z_REFVAL (parser -> info ));
565
565
zend_array * arr = Z_ARRVAL_P (Z_REFVAL (parser -> info ));
566
566
567
- size_t name_len = strlen (name );
568
- if ((element = zend_hash_str_find (arr , name , name_len )) == NULL ) {
567
+ if ((element = zend_hash_find (arr , name )) == NULL ) {
569
568
zval values ;
570
569
array_init (& values );
571
- element = zend_hash_str_update (arr , name , name_len , & values );
570
+ element = zend_hash_update (arr , name , & values );
572
571
}
573
572
574
573
add_next_index_long (element , parser -> curtag );
@@ -592,6 +591,17 @@ static zend_string *xml_decode_tag(xml_parser *parser, const XML_Char *tag)
592
591
}
593
592
/* }}} */
594
593
594
+ static zend_string * xml_stripped_tag (zend_string * tag_name , int offset )
595
+ {
596
+ if (offset == 0 ) {
597
+ return zend_string_copy (tag_name );
598
+ } else if (offset >= ZSTR_LEN (tag_name )) {
599
+ return ZSTR_EMPTY_ALLOC ();
600
+ } else {
601
+ return zend_string_init (ZSTR_VAL (tag_name ) + offset , ZSTR_LEN (tag_name ) - offset , false);
602
+ }
603
+ }
604
+
595
605
static zval * xml_get_separated_data (xml_parser * parser )
596
606
{
597
607
if (EXPECTED (Z_TYPE_P (Z_REFVAL (parser -> data )) == IS_ARRAY )) {
@@ -632,7 +642,7 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha
632
642
if (ZEND_FCC_INITIALIZED (parser -> startElementHandler )) {
633
643
zval args [3 ];
634
644
ZVAL_COPY (& args [0 ], & parser -> index );
635
- ZVAL_STRING (& args [1 ], SKIP_TAGSTART ( ZSTR_VAL ( tag_name ) ));
645
+ ZVAL_STR (& args [1 ], xml_stripped_tag ( tag_name , parser -> toffset ));
636
646
array_init (& args [2 ]);
637
647
638
648
while (attributes && * attributes ) {
@@ -651,7 +661,7 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha
651
661
652
662
zend_call_known_fcc (& parser -> startElementHandler , /* retval */ NULL , /* param_count */ 3 , args , /* named_params */ NULL );
653
663
zval_ptr_dtor (& args [0 ]);
654
- zval_ptr_dtor (& args [1 ]);
664
+ zval_ptr_dtor_str (& args [1 ]);
655
665
zval_ptr_dtor (& args [2 ]);
656
666
}
657
667
@@ -663,15 +673,15 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha
663
673
array_init (& tag );
664
674
array_init (& atr );
665
675
666
- char * skipped_tag_name = SKIP_TAGSTART (ZSTR_VAL (tag_name ));
667
-
668
- xml_add_to_info (parser , skipped_tag_name );
676
+ zend_string * stripped_tag = xml_stripped_tag (tag_name , parser -> toffset );
677
+ xml_add_to_info (parser , stripped_tag );
669
678
670
- add_assoc_string (& tag , "tag" , skipped_tag_name );
679
+ add_assoc_str (& tag , "tag" , stripped_tag ); /* transfer lifetime */
671
680
add_assoc_string (& tag , "type" , "open" );
672
681
add_assoc_long (& tag , "level" , parser -> level );
673
682
674
- parser -> ltags [parser -> level - 1 ] = estrdup (ZSTR_VAL (tag_name ));
683
+ /* Because toffset may change, we should use the original tag name */
684
+ parser -> ltags [parser -> level - 1 ] = zend_string_copy (tag_name );
675
685
parser -> lastwasopen = 1 ;
676
686
677
687
attributes = (const XML_Char * * ) attrs ;
@@ -733,11 +743,11 @@ void xml_endElementHandler(void *userData, const XML_Char *name)
733
743
if (ZEND_FCC_INITIALIZED (parser -> endElementHandler )) {
734
744
zval args [2 ];
735
745
ZVAL_COPY (& args [0 ], & parser -> index );
736
- ZVAL_STRING (& args [1 ], SKIP_TAGSTART ( ZSTR_VAL ( tag_name ) ));
746
+ ZVAL_STR (& args [1 ], xml_stripped_tag ( tag_name , parser -> toffset ));
737
747
738
748
zend_call_known_fcc (& parser -> endElementHandler , /* retval */ NULL , /* param_count */ 2 , args , /* named_params */ NULL );
739
749
zval_ptr_dtor (& args [0 ]);
740
- zval_ptr_dtor (& args [1 ]);
750
+ zval_ptr_dtor_str (& args [1 ]);
741
751
}
742
752
743
753
if (!Z_ISUNDEF (parser -> data ) && !EG (exception )) {
@@ -749,17 +759,19 @@ void xml_endElementHandler(void *userData, const XML_Char *name)
749
759
add_assoc_string (zv , "type" , "complete" );
750
760
}
751
761
} else {
752
- char * skipped_tag_name = SKIP_TAGSTART ( ZSTR_VAL ( tag_name ) );
762
+ zend_string * stripped_tag = xml_stripped_tag ( tag_name , parser -> toffset );
753
763
754
- xml_add_to_info (parser , skipped_tag_name );
764
+ xml_add_to_info (parser , stripped_tag );
755
765
756
766
zval * data = xml_get_separated_data (parser );
757
767
if (EXPECTED (data )) {
758
768
array_init (& tag );
759
- add_assoc_string (& tag , "tag" , skipped_tag_name );
769
+ add_assoc_str (& tag , "tag" , stripped_tag ); /* transfer lifetime */
760
770
add_assoc_string (& tag , "type" , "close" );
761
771
add_assoc_long (& tag , "level" , parser -> level );
762
772
zend_hash_next_index_insert (Z_ARRVAL_P (data ), & tag );
773
+ } else {
774
+ zend_string_release_ex (stripped_tag , false);
763
775
}
764
776
}
765
777
@@ -769,7 +781,11 @@ void xml_endElementHandler(void *userData, const XML_Char *name)
769
781
zend_string_release_ex (tag_name , 0 );
770
782
771
783
if ((parser -> ltags ) && (parser -> level <= XML_MAXLEVEL )) {
772
- efree (parser -> ltags [parser -> level - 1 ]);
784
+ zend_string * * str = & parser -> ltags [parser -> level - 1 ];
785
+ if (* str ) {
786
+ zend_string_release_ex (* str , false);
787
+ * str = NULL ;
788
+ }
773
789
}
774
790
775
791
parser -> level -- ;
@@ -792,7 +808,7 @@ void xml_characterDataHandler(void *userData, const XML_Char *s, int len)
792
808
793
809
zend_call_known_fcc (& parser -> characterDataHandler , /* retval */ NULL , /* param_count */ 2 , args , /* named_params */ NULL );
794
810
zval_ptr_dtor (& args [0 ]);
795
- zval_ptr_dtor (& args [1 ]);
811
+ zval_ptr_dtor_str (& args [1 ]);
796
812
}
797
813
798
814
if (Z_ISUNDEF (parser -> data ) || EG (exception )) {
@@ -868,8 +884,9 @@ void xml_characterDataHandler(void *userData, const XML_Char *s, int len)
868
884
} ZEND_HASH_FOREACH_END ();
869
885
if (parser -> level <= XML_MAXLEVEL && parser -> level > 0 && (doprint || (! parser -> skipwhite ))) {
870
886
array_init (& tag );
871
- xml_add_to_info (parser ,SKIP_TAGSTART (parser -> ltags [parser -> level - 1 ]));
872
- add_assoc_string (& tag , "tag" , SKIP_TAGSTART (parser -> ltags [parser -> level - 1 ]));
887
+ zend_string * stripped_tag = xml_stripped_tag (parser -> ltags [parser -> level - 1 ], parser -> toffset );
888
+ xml_add_to_info (parser , stripped_tag );
889
+ add_assoc_str (& tag , "tag" , stripped_tag ); /* transfer lifetime */
873
890
add_assoc_str (& tag , "value" , decoded_value );
874
891
add_assoc_string (& tag , "type" , "cdata" );
875
892
add_assoc_long (& tag , "level" , parser -> level );
@@ -900,8 +917,8 @@ void xml_processingInstructionHandler(void *userData, const XML_Char *target, co
900
917
901
918
zend_call_known_fcc (& parser -> processingInstructionHandler , /* retval */ NULL , /* param_count */ 3 , args , /* named_params */ NULL );
902
919
zval_ptr_dtor (& args [0 ]);
903
- zval_ptr_dtor (& args [1 ]);
904
- zval_ptr_dtor (& args [2 ]);
920
+ zval_ptr_dtor_str (& args [1 ]);
921
+ zval_ptr_dtor_str (& args [2 ]);
905
922
}
906
923
/* }}} */
907
924
@@ -921,7 +938,7 @@ void xml_defaultHandler(void *userData, const XML_Char *s, int len)
921
938
922
939
zend_call_known_fcc (& parser -> defaultHandler , /* retval */ NULL , /* param_count */ 2 , args , /* named_params */ NULL );
923
940
zval_ptr_dtor (& args [0 ]);
924
- zval_ptr_dtor (& args [1 ]);
941
+ zval_ptr_dtor_str (& args [1 ]);
925
942
}
926
943
/* }}} */
927
944
@@ -947,11 +964,11 @@ void xml_unparsedEntityDeclHandler(void *userData,
947
964
948
965
zend_call_known_fcc (& parser -> unparsedEntityDeclHandler , /* retval */ NULL , /* param_count */ 6 , args , /* named_params */ NULL );
949
966
zval_ptr_dtor (& args [0 ]);
950
- zval_ptr_dtor (& args [1 ]);
951
- zval_ptr_dtor (& args [2 ]);
952
- zval_ptr_dtor (& args [3 ]);
953
- zval_ptr_dtor (& args [4 ]);
954
- zval_ptr_dtor (& args [5 ]);
967
+ zval_ptr_dtor_str (& args [1 ]);
968
+ zval_ptr_dtor_str (& args [2 ]);
969
+ zval_ptr_dtor_str (& args [3 ]);
970
+ zval_ptr_dtor_str (& args [4 ]);
971
+ zval_ptr_dtor_str (& args [5 ]);
955
972
}
956
973
/* }}} */
957
974
@@ -975,10 +992,10 @@ void xml_notationDeclHandler(void *userData, const XML_Char *notationName,
975
992
976
993
zend_call_known_fcc (& parser -> notationDeclHandler , /* retval */ NULL , /* param_count */ 5 , args , /* named_params */ NULL );
977
994
zval_ptr_dtor (& args [0 ]);
978
- zval_ptr_dtor (& args [1 ]);
979
- zval_ptr_dtor (& args [2 ]);
980
- zval_ptr_dtor (& args [3 ]);
981
- zval_ptr_dtor (& args [4 ]);
995
+ zval_ptr_dtor_str (& args [1 ]);
996
+ zval_ptr_dtor_str (& args [2 ]);
997
+ zval_ptr_dtor_str (& args [3 ]);
998
+ zval_ptr_dtor_str (& args [4 ]);
982
999
}
983
1000
/* }}} */
984
1001
@@ -1004,10 +1021,10 @@ int xml_externalEntityRefHandler(XML_Parser userData, const XML_Char *openEntity
1004
1021
1005
1022
zend_call_known_fcc (& parser -> externalEntityRefHandler , /* retval */ & retval , /* param_count */ 5 , args , /* named_params */ NULL );
1006
1023
zval_ptr_dtor (& args [0 ]);
1007
- zval_ptr_dtor (& args [1 ]);
1008
- zval_ptr_dtor (& args [2 ]);
1009
- zval_ptr_dtor (& args [3 ]);
1010
- zval_ptr_dtor (& args [4 ]);
1024
+ zval_ptr_dtor_str (& args [1 ]);
1025
+ zval_ptr_dtor_str (& args [2 ]);
1026
+ zval_ptr_dtor_str (& args [3 ]);
1027
+ zval_ptr_dtor_str (& args [4 ]);
1011
1028
1012
1029
/* TODO Better handling from callable return value */
1013
1030
if (!Z_ISUNDEF (retval )) {
@@ -1037,8 +1054,8 @@ void xml_startNamespaceDeclHandler(void *userData,const XML_Char *prefix, const
1037
1054
1038
1055
zend_call_known_fcc (& parser -> startNamespaceDeclHandler , /* retval */ NULL , /* param_count */ 3 , args , /* named_params */ NULL );
1039
1056
zval_ptr_dtor (& args [0 ]);
1040
- zval_ptr_dtor (& args [1 ]);
1041
- zval_ptr_dtor (& args [2 ]);
1057
+ zval_ptr_dtor_str (& args [1 ]);
1058
+ zval_ptr_dtor_str (& args [2 ]);
1042
1059
}
1043
1060
/* }}} */
1044
1061
@@ -1058,7 +1075,7 @@ void xml_endNamespaceDeclHandler(void *userData, const XML_Char *prefix)
1058
1075
1059
1076
zend_call_known_fcc (& parser -> endNamespaceDeclHandler , /* retval */ NULL , /* param_count */ 2 , args , /* named_params */ NULL );
1060
1077
zval_ptr_dtor (& args [0 ]);
1061
- zval_ptr_dtor (& args [1 ]);
1078
+ zval_ptr_dtor_str (& args [1 ]);
1062
1079
}
1063
1080
/* }}} */
1064
1081
@@ -1448,8 +1465,7 @@ PHP_FUNCTION(xml_parse_into_struct)
1448
1465
1449
1466
parser -> level = 0 ;
1450
1467
xml_parser_free_ltags (parser );
1451
- parser -> ltags = safe_emalloc (XML_MAXLEVEL , sizeof (char * ), 0 );
1452
- memset (parser -> ltags , 0 , XML_MAXLEVEL * sizeof (char * ));
1468
+ parser -> ltags = ecalloc (XML_MAXLEVEL , sizeof (zend_string * ));
1453
1469
1454
1470
XML_SetElementHandler (parser -> parser , xml_startElementHandler , xml_endElementHandler );
1455
1471
XML_SetCharacterDataHandler (parser -> parser , xml_characterDataHandler );
0 commit comments