From 7d163e8a0880ae8af2dd869071393e5dc07ef271 Mon Sep 17 00:00:00 2001 From: Rob Richards Date: Sat, 6 Jul 2013 07:53:07 -0400 Subject: [PATCH] truncate results at depth of 255 to prevent corruption --- ext/xml/xml.c | 90 +++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 1f0480b..9f0bc30 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -428,7 +428,7 @@ static void xml_parser_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) } if (parser->ltags) { int inx; - for (inx = 0; inx < parser->level; inx++) + for (inx = 0; ((inx < parser->level) && (inx < XML_MAXLEVEL)); inx++) efree(parser->ltags[ inx ]); efree(parser->ltags); } @@ -805,45 +805,50 @@ void _xml_startElementHandler(void *userData, const XML_Char *name, const XML_Ch } if (parser->data) { - zval *tag, *atr; - int atcnt = 0; + if (parser->level <= XML_MAXLEVEL) { + zval *tag, *atr; + int atcnt = 0; - MAKE_STD_ZVAL(tag); - MAKE_STD_ZVAL(atr); + MAKE_STD_ZVAL(tag); + MAKE_STD_ZVAL(atr); - array_init(tag); - array_init(atr); + array_init(tag); + array_init(atr); - _xml_add_to_info(parser,((char *) tag_name) + parser->toffset); + _xml_add_to_info(parser,((char *) tag_name) + parser->toffset); - add_assoc_string(tag,"tag",((char *) tag_name) + parser->toffset,1); /* cast to avoid gcc-warning */ - add_assoc_string(tag,"type","open",1); - add_assoc_long(tag,"level",parser->level); + add_assoc_string(tag,"tag",((char *) tag_name) + parser->toffset,1); /* cast to avoid gcc-warning */ + add_assoc_string(tag,"type","open",1); + add_assoc_long(tag,"level",parser->level); - parser->ltags[parser->level-1] = estrdup(tag_name); - parser->lastwasopen = 1; + parser->ltags[parser->level-1] = estrdup(tag_name); + parser->lastwasopen = 1; - attributes = (const XML_Char **) attrs; + attributes = (const XML_Char **) attrs; - while (attributes && *attributes) { - att = _xml_decode_tag(parser, attributes[0]); - val = xml_utf8_decode(attributes[1], strlen(attributes[1]), &val_len, parser->target_encoding); - - add_assoc_stringl(atr,att,val,val_len,0); + while (attributes && *attributes) { + att = _xml_decode_tag(parser, attributes[0]); + val = xml_utf8_decode(attributes[1], strlen(attributes[1]), &val_len, parser->target_encoding); - atcnt++; - attributes += 2; + add_assoc_stringl(atr,att,val,val_len,0); - efree(att); - } + atcnt++; + attributes += 2; - if (atcnt) { - zend_hash_add(Z_ARRVAL_P(tag),"attributes",sizeof("attributes"),&atr,sizeof(zval*),NULL); - } else { - zval_ptr_dtor(&atr); - } + efree(att); + } + + if (atcnt) { + zend_hash_add(Z_ARRVAL_P(tag),"attributes",sizeof("attributes"),&atr,sizeof(zval*),NULL); + } else { + zval_ptr_dtor(&atr); + } - zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),(void *) &parser->ctag); + zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),(void *) &parser->ctag); + } else if (parser->level == (XML_MAXLEVEL + 1)) { + TSRMLS_FETCH(); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Maximum depth exceeded - Results truncated"); + } } efree(tag_name); @@ -895,7 +900,7 @@ void _xml_endElementHandler(void *userData, const XML_Char *name) efree(tag_name); - if (parser->ltags) { + if ((parser->ltags) && (parser->level <= XML_MAXLEVEL)) { efree(parser->ltags[parser->level-1]); } @@ -979,18 +984,23 @@ void _xml_characterDataHandler(void *userData, const XML_Char *s, int len) } } - MAKE_STD_ZVAL(tag); - - array_init(tag); - - _xml_add_to_info(parser,parser->ltags[parser->level-1] + parser->toffset); + if (parser->level <= XML_MAXLEVEL) { + MAKE_STD_ZVAL(tag); - add_assoc_string(tag,"tag",parser->ltags[parser->level-1] + parser->toffset,1); - add_assoc_string(tag,"value",decoded_value,0); - add_assoc_string(tag,"type","cdata",1); - add_assoc_long(tag,"level",parser->level); + array_init(tag); - zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),NULL); + _xml_add_to_info(parser,parser->ltags[parser->level-1] + parser->toffset); + + add_assoc_string(tag,"tag",parser->ltags[parser->level-1] + parser->toffset,1); + add_assoc_string(tag,"value",decoded_value,0); + add_assoc_string(tag,"type","cdata",1); + add_assoc_long(tag,"level",parser->level); + + zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),NULL); + } else if (parser->level == (XML_MAXLEVEL + 1)) { + TSRMLS_FETCH(); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Maximum depth exceeded - Results truncated"); + } } } else { efree(decoded_value); -- 1.7.11.5 From 710eee5555bc5c95692bd3c84f5d2b5d687349b6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Johannes=20Schl=C3=BCter?= Date: Wed, 10 Jul 2013 19:35:18 +0200 Subject: [PATCH] add test for bug #65236 --- ext/xml/tests/bug65236.phpt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 ext/xml/tests/bug65236.phpt diff --git a/ext/xml/tests/bug65236.phpt b/ext/xml/tests/bug65236.phpt new file mode 100644 index 0000000..67b26d6 --- /dev/null +++ b/ext/xml/tests/bug65236.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #65236 (heap corruption in xml parser) +--SKIPIF-- + +--FILE-- +", 1000), $a); + +echo "Done\n"; +?> +--EXPECTF-- +Warning: xml_parse_into_struct(): Maximum depth exceeded - Results truncated in %s on line %d +Done -- 1.7.11.5