@@ -91,6 +91,7 @@ typedef struct {
9191 int lastwasopen ;
9292 int skipwhite ;
9393 int isparsing ;
94+ bool parsehuge ;
9495
9596 XML_Char * baseURI ;
9697
@@ -264,6 +265,28 @@ PHP_MINFO_FUNCTION(xml)
264265
265266/* {{{ extension-internal functions */
266267
268+ static int xml_parse_helper (xml_parser * parser , const char * data , size_t data_len , bool is_final )
269+ {
270+ ZEND_ASSERT (!parser -> isparsing );
271+
272+ /* libxml2 specific options */
273+ #if LIBXML_EXPAT_COMPAT
274+ /* See xmlInitSAXParserCtxt() and xmlCtxtUseOptions() */
275+ if (parser -> parsehuge ) {
276+ parser -> parser -> parser -> options |= XML_PARSE_HUGE ;
277+ xmlDictSetLimit (parser -> parser -> parser -> dict , 0 );
278+ } else {
279+ parser -> parser -> parser -> options &= ~XML_PARSE_HUGE ;
280+ xmlDictSetLimit (parser -> parser -> parser -> dict , XML_MAX_DICTIONARY_LIMIT );
281+ }
282+ #endif
283+
284+ parser -> isparsing = 1 ;
285+ int ret = XML_Parse (parser -> parser , (const XML_Char * ) data , data_len , is_final );
286+ parser -> isparsing = 0 ;
287+ return ret ;
288+ }
289+
267290static void _xml_xmlchar_zval (const XML_Char * s , int len , const XML_Char * encoding , zval * ret )
268291{
269292 if (s == NULL ) {
@@ -1024,6 +1047,7 @@ static void php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAMETERS, int ns_supp
10241047 parser -> target_encoding = encoding ;
10251048 parser -> case_folding = 1 ;
10261049 parser -> isparsing = 0 ;
1050+ parser -> parsehuge = false; /* It's the default for BC & DoS protection */
10271051
10281052 XML_SetUserData (parser -> parser , parser );
10291053 ZVAL_COPY_VALUE (& parser -> index , return_value );
@@ -1283,7 +1307,6 @@ PHP_FUNCTION(xml_parse)
12831307 zval * pind ;
12841308 char * data ;
12851309 size_t data_len ;
1286- int ret ;
12871310 bool isFinal = 0 ;
12881311
12891312 if (zend_parse_parameters (ZEND_NUM_ARGS (), "Os|b" , & pind , xml_parser_ce , & data , & data_len , & isFinal ) == FAILURE ) {
@@ -1295,10 +1318,7 @@ PHP_FUNCTION(xml_parse)
12951318 zend_throw_error (NULL , "Parser must not be called recursively" );
12961319 RETURN_THROWS ();
12971320 }
1298- parser -> isparsing = 1 ;
1299- ret = XML_Parse (parser -> parser , (XML_Char * )data , data_len , isFinal );
1300- parser -> isparsing = 0 ;
1301- RETVAL_LONG (ret );
1321+ RETURN_LONG (xml_parse_helper (parser , data , data_len , isFinal ));
13021322}
13031323
13041324/* }}} */
@@ -1310,7 +1330,6 @@ PHP_FUNCTION(xml_parse_into_struct)
13101330 zval * pind , * xdata , * info = NULL ;
13111331 char * data ;
13121332 size_t data_len ;
1313- int ret ;
13141333
13151334 if (zend_parse_parameters (ZEND_NUM_ARGS (), "Osz|z" , & pind , xml_parser_ce , & data , & data_len , & xdata , & info ) == FAILURE ) {
13161335 RETURN_THROWS ();
@@ -1348,11 +1367,7 @@ PHP_FUNCTION(xml_parse_into_struct)
13481367 XML_SetElementHandler (parser -> parser , _xml_startElementHandler , _xml_endElementHandler );
13491368 XML_SetCharacterDataHandler (parser -> parser , _xml_characterDataHandler );
13501369
1351- parser -> isparsing = 1 ;
1352- ret = XML_Parse (parser -> parser , (XML_Char * )data , data_len , 1 );
1353- parser -> isparsing = 0 ;
1354-
1355- RETVAL_LONG (ret );
1370+ RETURN_LONG (xml_parse_helper (parser , data , data_len , true));
13561371}
13571372/* }}} */
13581373
@@ -1481,6 +1496,15 @@ PHP_FUNCTION(xml_parser_set_option)
14811496 case PHP_XML_OPTION_SKIP_WHITE :
14821497 parser -> skipwhite = zend_is_true (value );
14831498 break ;
1499+ /* Boolean option */
1500+ case PHP_XML_OPTION_PARSE_HUGE :
1501+ /* Prevent wreaking havock to the parser internals during parsing */
1502+ if (UNEXPECTED (parser -> isparsing )) {
1503+ zend_throw_error (NULL , "Cannot change option XML_OPTION_PARSE_HUGE while parsing" );
1504+ RETURN_THROWS ();
1505+ }
1506+ parser -> parsehuge = zend_is_true (value );
1507+ break ;
14841508 /* Integer option */
14851509 case PHP_XML_OPTION_SKIP_TAGSTART :
14861510 /* The tag start offset is stored in an int */
@@ -1542,6 +1566,9 @@ PHP_FUNCTION(xml_parser_get_option)
15421566 case PHP_XML_OPTION_SKIP_WHITE :
15431567 RETURN_BOOL (parser -> skipwhite );
15441568 break ;
1569+ case PHP_XML_OPTION_PARSE_HUGE :
1570+ RETURN_BOOL (parser -> parsehuge );
1571+ break ;
15451572 case PHP_XML_OPTION_TARGET_ENCODING :
15461573 RETURN_STRING ((char * )parser -> target_encoding );
15471574 break ;
0 commit comments