mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Fix GH-16465: Heap buffer overflow in DOMNode->getElementByTagName
If the input contains NUL bytes then the length doesn't match the actual duplicated string's length. Note that libxml can't handle this properly anyway so we just reject NUL bytes and too long strings. Closes GH-16467.
This commit is contained in:
parent
ef1c3b82ff
commit
d70f3ba9a5
4 changed files with 51 additions and 9 deletions
2
NEWS
2
NEWS
|
@ -26,6 +26,8 @@ PHP NEWS
|
||||||
. Fixed bug GH-16316 (DOMXPath breaks when not initialized properly).
|
. Fixed bug GH-16316 (DOMXPath breaks when not initialized properly).
|
||||||
(nielsdos)
|
(nielsdos)
|
||||||
. Add missing hierarchy checks to replaceChild. (nielsdos)
|
. Add missing hierarchy checks to replaceChild. (nielsdos)
|
||||||
|
. Fixed bug GH-16465 (Heap buffer overflow in DOMNode->getElementByTagName).
|
||||||
|
(nielsdos)
|
||||||
|
|
||||||
- EXIF:
|
- EXIF:
|
||||||
. Fixed bug GH-16409 (Segfault in exif_thumbnail when not dealing with a
|
. Fixed bug GH-16409 (Segfault in exif_thumbnail when not dealing with a
|
||||||
|
|
|
@ -816,7 +816,12 @@ static void dom_element_get_elements_by_tag_name(INTERNAL_FUNCTION_PARAMETERS, b
|
||||||
dom_object *intern, *namednode;
|
dom_object *intern, *namednode;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &name, &name_len) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name_len > INT_MAX) {
|
||||||
|
zend_argument_value_error(1, "is too long");
|
||||||
RETURN_THROWS();
|
RETURN_THROWS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1239,7 +1244,17 @@ static void dom_element_get_elements_by_tag_name_ns(INTERNAL_FUNCTION_PARAMETERS
|
||||||
dom_object *intern, *namednode;
|
dom_object *intern, *namednode;
|
||||||
char *uri, *name;
|
char *uri, *name;
|
||||||
|
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p!p", &uri, &uri_len, &name, &name_len) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uri_len > INT_MAX) {
|
||||||
|
zend_argument_value_error(1, "is too long");
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name_len > INT_MAX) {
|
||||||
|
zend_argument_value_error(2, "is too long");
|
||||||
RETURN_THROWS();
|
RETURN_THROWS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1473,7 +1473,7 @@ void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xml
|
||||||
const xmlChar* tmp;
|
const xmlChar* tmp;
|
||||||
|
|
||||||
if (local) {
|
if (local) {
|
||||||
int len = local_len > INT_MAX ? -1 : (int) local_len;
|
int len = (int) local_len;
|
||||||
if (doc != NULL && (tmp = xmlDictExists(doc->dict, (const xmlChar *)local, len)) != NULL) {
|
if (doc != NULL && (tmp = xmlDictExists(doc->dict, (const xmlChar *)local, len)) != NULL) {
|
||||||
mapptr->local = BAD_CAST tmp;
|
mapptr->local = BAD_CAST tmp;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1481,15 +1481,11 @@ void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xml
|
||||||
mapptr->free_local = true;
|
mapptr->free_local = true;
|
||||||
}
|
}
|
||||||
mapptr->local_lower = BAD_CAST estrdup(local);
|
mapptr->local_lower = BAD_CAST estrdup(local);
|
||||||
if (len < 0) {
|
|
||||||
zend_str_tolower((char *) mapptr->local_lower, strlen((const char *) mapptr->local_lower));
|
|
||||||
} else {
|
|
||||||
zend_str_tolower((char *) mapptr->local_lower, len);
|
zend_str_tolower((char *) mapptr->local_lower, len);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (ns) {
|
if (ns) {
|
||||||
int len = ns_len > INT_MAX ? -1 : (int) ns_len;
|
int len = (int) ns_len;
|
||||||
if (doc != NULL && (tmp = xmlDictExists(doc->dict, (const xmlChar *)ns, len)) != NULL) {
|
if (doc != NULL && (tmp = xmlDictExists(doc->dict, (const xmlChar *)ns, len)) != NULL) {
|
||||||
mapptr->ns = BAD_CAST tmp;
|
mapptr->ns = BAD_CAST tmp;
|
||||||
} else {
|
} else {
|
||||||
|
|
29
ext/dom/tests/gh16465.phpt
Normal file
29
ext/dom/tests/gh16465.phpt
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
--TEST--
|
||||||
|
GH-16465 (Heap buffer overflow in DOMNode->getElementByTagName)
|
||||||
|
--EXTENSIONS--
|
||||||
|
dom
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$v10 = new DOMElement("a");
|
||||||
|
try {
|
||||||
|
$v10->getElementsByTagName("text\0something");
|
||||||
|
} catch (ValueError $e) {
|
||||||
|
echo $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$v10->getElementsByTagNameNS("", "text\0something");
|
||||||
|
} catch (ValueError $e) {
|
||||||
|
echo $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$v10->getElementsByTagNameNS("text\0something", "");
|
||||||
|
} catch (ValueError $e) {
|
||||||
|
echo $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
DOMElement::getElementsByTagName(): Argument #1 ($qualifiedName) must not contain any null bytes
|
||||||
|
DOMElement::getElementsByTagNameNS(): Argument #2 ($localName) must not contain any null bytes
|
||||||
|
DOMElement::getElementsByTagNameNS(): Argument #1 ($namespace) must not contain any null bytes
|
Loading…
Add table
Add a link
Reference in a new issue