@@ -86,7 +86,7 @@ typedef struct {
8686 int toffset ;
8787 int curtag ;
8888 zend_long ctag_index ;
89- char * * ltags ;
89+ zend_string * * ltags ;
9090 bool lastwasopen ;
9191 bool skipwhite ;
9292 bool isparsing ;
@@ -116,8 +116,6 @@ ZEND_GET_MODULE(xml)
116116
117117#define XML_MAXLEVEL 255 /* XXX this should be dynamic */
118118
119- #define SKIP_TAGSTART (str ) ((str) + (parser->toffset > strlen(str) ? strlen(str) : parser->toffset))
120-
121119static zend_class_entry * xml_parser_ce ;
122120static zend_object_handlers xml_parser_object_handlers ;
123121
@@ -138,7 +136,7 @@ inline static unsigned short xml_encode_us_ascii(unsigned char);
138136inline static char xml_decode_us_ascii (unsigned short );
139137static void xml_xmlchar_zval (const XML_Char * , int , const XML_Char * , zval * );
140138static 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 );
142140inline static zend_string * xml_decode_tag (xml_parser * parser , const XML_Char * tag );
143141
144142void xml_startElementHandler (void * , const XML_Char * , const XML_Char * * );
@@ -311,7 +309,6 @@ static inline xml_parser *xml_parser_from_obj(zend_object *obj) {
311309
312310static zend_object * xml_parser_create_object (zend_class_entry * class_type ) {
313311 xml_parser * intern = zend_object_alloc (sizeof (xml_parser ), class_type );
314- memset (intern , 0 , sizeof (xml_parser ) - sizeof (zend_object ));
315312
316313 zend_object_std_init (& intern -> std , class_type );
317314 object_properties_init (& intern -> std , class_type );
@@ -323,8 +320,11 @@ static void xml_parser_free_ltags(xml_parser *parser)
323320{
324321 if (parser -> ltags ) {
325322 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+ }
328328 efree (parser -> ltags );
329329 }
330330}
@@ -553,7 +553,7 @@ static int xml_xmlcharlen(const XML_Char *s)
553553/* }}} */
554554
555555/* {{{ 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 )
557557{
558558 zval * element ;
559559
@@ -564,11 +564,10 @@ static void xml_add_to_info(xml_parser *parser, const char *name)
564564 SEPARATE_ARRAY (Z_REFVAL (parser -> info ));
565565 zend_array * arr = Z_ARRVAL_P (Z_REFVAL (parser -> info ));
566566
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 ) {
569568 zval values ;
570569 array_init (& values );
571- element = zend_hash_str_update (arr , name , name_len , & values );
570+ element = zend_hash_update (arr , name , & values );
572571 }
573572
574573 add_next_index_long (element , parser -> curtag );
@@ -592,6 +591,17 @@ static zend_string *xml_decode_tag(xml_parser *parser, const XML_Char *tag)
592591}
593592/* }}} */
594593
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+
595605static zval * xml_get_separated_data (xml_parser * parser )
596606{
597607 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
632642 if (ZEND_FCC_INITIALIZED (parser -> startElementHandler )) {
633643 zval args [3 ];
634644 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 ));
636646 array_init (& args [2 ]);
637647
638648 while (attributes && * attributes ) {
@@ -651,7 +661,7 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha
651661
652662 zend_call_known_fcc (& parser -> startElementHandler , /* retval */ NULL , /* param_count */ 3 , args , /* named_params */ NULL );
653663 zval_ptr_dtor (& args [0 ]);
654- zval_ptr_dtor (& args [1 ]);
664+ zval_ptr_dtor_str (& args [1 ]);
655665 zval_ptr_dtor (& args [2 ]);
656666 }
657667
@@ -663,15 +673,15 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha
663673 array_init (& tag );
664674 array_init (& atr );
665675
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 );
669678
670- add_assoc_string (& tag , "tag" , skipped_tag_name );
679+ add_assoc_str (& tag , "tag" , stripped_tag ); /* transfer lifetime */
671680 add_assoc_string (& tag , "type" , "open" );
672681 add_assoc_long (& tag , "level" , parser -> level );
673682
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 );
675685 parser -> lastwasopen = 1 ;
676686
677687 attributes = (const XML_Char * * ) attrs ;
@@ -733,11 +743,11 @@ void xml_endElementHandler(void *userData, const XML_Char *name)
733743 if (ZEND_FCC_INITIALIZED (parser -> endElementHandler )) {
734744 zval args [2 ];
735745 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 ));
737747
738748 zend_call_known_fcc (& parser -> endElementHandler , /* retval */ NULL , /* param_count */ 2 , args , /* named_params */ NULL );
739749 zval_ptr_dtor (& args [0 ]);
740- zval_ptr_dtor (& args [1 ]);
750+ zval_ptr_dtor_str (& args [1 ]);
741751 }
742752
743753 if (!Z_ISUNDEF (parser -> data ) && !EG (exception )) {
@@ -749,17 +759,19 @@ void xml_endElementHandler(void *userData, const XML_Char *name)
749759 add_assoc_string (zv , "type" , "complete" );
750760 }
751761 } else {
752- char * skipped_tag_name = SKIP_TAGSTART ( ZSTR_VAL ( tag_name ) );
762+ zend_string * stripped_tag = xml_stripped_tag ( tag_name , parser -> toffset );
753763
754- xml_add_to_info (parser , skipped_tag_name );
764+ xml_add_to_info (parser , stripped_tag );
755765
756766 zval * data = xml_get_separated_data (parser );
757767 if (EXPECTED (data )) {
758768 array_init (& tag );
759- add_assoc_string (& tag , "tag" , skipped_tag_name );
769+ add_assoc_str (& tag , "tag" , stripped_tag ); /* transfer lifetime */
760770 add_assoc_string (& tag , "type" , "close" );
761771 add_assoc_long (& tag , "level" , parser -> level );
762772 zend_hash_next_index_insert (Z_ARRVAL_P (data ), & tag );
773+ } else {
774+ zend_string_release_ex (stripped_tag , false);
763775 }
764776 }
765777
@@ -769,7 +781,11 @@ void xml_endElementHandler(void *userData, const XML_Char *name)
769781 zend_string_release_ex (tag_name , 0 );
770782
771783 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+ }
773789 }
774790
775791 parser -> level -- ;
@@ -792,7 +808,7 @@ void xml_characterDataHandler(void *userData, const XML_Char *s, int len)
792808
793809 zend_call_known_fcc (& parser -> characterDataHandler , /* retval */ NULL , /* param_count */ 2 , args , /* named_params */ NULL );
794810 zval_ptr_dtor (& args [0 ]);
795- zval_ptr_dtor (& args [1 ]);
811+ zval_ptr_dtor_str (& args [1 ]);
796812 }
797813
798814 if (Z_ISUNDEF (parser -> data ) || EG (exception )) {
@@ -868,8 +884,9 @@ void xml_characterDataHandler(void *userData, const XML_Char *s, int len)
868884 } ZEND_HASH_FOREACH_END ();
869885 if (parser -> level <= XML_MAXLEVEL && parser -> level > 0 && (doprint || (! parser -> skipwhite ))) {
870886 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 */
873890 add_assoc_str (& tag , "value" , decoded_value );
874891 add_assoc_string (& tag , "type" , "cdata" );
875892 add_assoc_long (& tag , "level" , parser -> level );
@@ -900,8 +917,8 @@ void xml_processingInstructionHandler(void *userData, const XML_Char *target, co
900917
901918 zend_call_known_fcc (& parser -> processingInstructionHandler , /* retval */ NULL , /* param_count */ 3 , args , /* named_params */ NULL );
902919 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 ]);
905922}
906923/* }}} */
907924
@@ -921,7 +938,7 @@ void xml_defaultHandler(void *userData, const XML_Char *s, int len)
921938
922939 zend_call_known_fcc (& parser -> defaultHandler , /* retval */ NULL , /* param_count */ 2 , args , /* named_params */ NULL );
923940 zval_ptr_dtor (& args [0 ]);
924- zval_ptr_dtor (& args [1 ]);
941+ zval_ptr_dtor_str (& args [1 ]);
925942}
926943/* }}} */
927944
@@ -947,11 +964,11 @@ void xml_unparsedEntityDeclHandler(void *userData,
947964
948965 zend_call_known_fcc (& parser -> unparsedEntityDeclHandler , /* retval */ NULL , /* param_count */ 6 , args , /* named_params */ NULL );
949966 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 ]);
955972}
956973/* }}} */
957974
@@ -975,10 +992,10 @@ void xml_notationDeclHandler(void *userData, const XML_Char *notationName,
975992
976993 zend_call_known_fcc (& parser -> notationDeclHandler , /* retval */ NULL , /* param_count */ 5 , args , /* named_params */ NULL );
977994 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 ]);
982999}
9831000/* }}} */
9841001
@@ -1004,10 +1021,10 @@ int xml_externalEntityRefHandler(XML_Parser userData, const XML_Char *openEntity
10041021
10051022 zend_call_known_fcc (& parser -> externalEntityRefHandler , /* retval */ & retval , /* param_count */ 5 , args , /* named_params */ NULL );
10061023 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 ]);
10111028
10121029 /* TODO Better handling from callable return value */
10131030 if (!Z_ISUNDEF (retval )) {
@@ -1037,8 +1054,8 @@ void xml_startNamespaceDeclHandler(void *userData,const XML_Char *prefix, const
10371054
10381055 zend_call_known_fcc (& parser -> startNamespaceDeclHandler , /* retval */ NULL , /* param_count */ 3 , args , /* named_params */ NULL );
10391056 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 ]);
10421059}
10431060/* }}} */
10441061
@@ -1058,7 +1075,7 @@ void xml_endNamespaceDeclHandler(void *userData, const XML_Char *prefix)
10581075
10591076 zend_call_known_fcc (& parser -> endNamespaceDeclHandler , /* retval */ NULL , /* param_count */ 2 , args , /* named_params */ NULL );
10601077 zval_ptr_dtor (& args [0 ]);
1061- zval_ptr_dtor (& args [1 ]);
1078+ zval_ptr_dtor_str (& args [1 ]);
10621079}
10631080/* }}} */
10641081
@@ -1448,8 +1465,7 @@ PHP_FUNCTION(xml_parse_into_struct)
14481465
14491466 parser -> level = 0 ;
14501467 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 * ));
14531469
14541470 XML_SetElementHandler (parser -> parser , xml_startElementHandler , xml_endElementHandler );
14551471 XML_SetCharacterDataHandler (parser -> parser , xml_characterDataHandler );
0 commit comments