mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Fix GH-12392: Segmentation fault on SoapClient::__getTypes
There are two issues: - UAF because the hashmap resized while being iterated over, yet the local variables used internally in the macros are not updated. - The hashmap being iterated over is modified: entries are deleted after other entries have been added. This causes the deletion to fail sometimes because indices of buckets have shifted. Fix it by using a while loop iteration and HashPosition position tracker instead. Issue exists on PHP 8.1 too, but is much harder to trigger. The test file reproduces the issue reliably on PHP 8.2 and up. Closes GH-12409.
This commit is contained in:
parent
71f14510f6
commit
7e4a3236d9
4 changed files with 105 additions and 6 deletions
4
NEWS
4
NEWS
|
@ -10,6 +10,10 @@ PHP NEWS
|
|||
. Fixed bug GH-8143 (Crashes in zend_accel_inheritance_cache_find since
|
||||
upgrading to 8.1.3 due to corrupt on-disk file cache). (turchanov)
|
||||
|
||||
- SOAP:
|
||||
. Fixed bug GH-12392 (Segmentation fault on SoapClient::__getTypes).
|
||||
(nielsdos)
|
||||
|
||||
26 Oct 2023, PHP 8.1.25
|
||||
|
||||
- Core:
|
||||
|
|
|
@ -2261,17 +2261,23 @@ static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type)
|
|||
schema_content_model_fixup(ctx, type->model);
|
||||
}
|
||||
if (type->attributes) {
|
||||
zend_string *str_key;
|
||||
zend_ulong index;
|
||||
HashPosition pos;
|
||||
zend_hash_internal_pointer_reset_ex(type->attributes, &pos);
|
||||
|
||||
ZEND_HASH_FOREACH_KEY_PTR(type->attributes, index, str_key, attr) {
|
||||
if (str_key) {
|
||||
while ((attr = zend_hash_get_current_data_ptr_ex(type->attributes, &pos)) != NULL) {
|
||||
zend_string *str_key;
|
||||
zend_ulong index;
|
||||
|
||||
if (zend_hash_get_current_key_ex(type->attributes, &str_key, &index, &pos) == HASH_KEY_IS_STRING) {
|
||||
schema_attribute_fixup(ctx, attr);
|
||||
zend_result result = zend_hash_move_forward_ex(type->attributes, &pos);
|
||||
ZEND_ASSERT(result == SUCCESS);
|
||||
} else {
|
||||
schema_attributegroup_fixup(ctx, attr, type->attributes);
|
||||
zend_hash_index_del(type->attributes, index);
|
||||
zend_result result = zend_hash_index_del(type->attributes, index);
|
||||
ZEND_ASSERT(result == SUCCESS);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
28
ext/soap/tests/gh12392.phpt
Normal file
28
ext/soap/tests/gh12392.phpt
Normal file
|
@ -0,0 +1,28 @@
|
|||
--TEST--
|
||||
GH-12392 (Segmentation fault on SoapClient::__getTypes)
|
||||
--EXTENSIONS--
|
||||
soap
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$client = new SoapClient(__DIR__ . "/gh12392.wsdl", ['cache_wsdl' => WSDL_CACHE_NONE]);
|
||||
echo 'Client created!' . "\n";
|
||||
|
||||
$types = $client->__getTypes();
|
||||
echo 'Got types!' . "\n";
|
||||
|
||||
var_dump($types);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Client created!
|
||||
Got types!
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(62) "struct dummy {
|
||||
string foo;
|
||||
string a;
|
||||
string b;
|
||||
string c;
|
||||
}"
|
||||
}
|
61
ext/soap/tests/gh12392.wsdl
Normal file
61
ext/soap/tests/gh12392.wsdl
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<wsdl:definitions
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
|
||||
xmlns="http://schemas.xmlsoap.org/wsdl/"
|
||||
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
||||
targetNamespace="http://xoev.de/schemata/xzufi/2_2_0">
|
||||
<wsdl:types>
|
||||
<xs:schema xmlns:ns="http://php.net" targetNamespace="http://php.net">
|
||||
<xs:attributeGroup name="c">
|
||||
<xs:attribute name="c" type="string" />
|
||||
</xs:attributeGroup>
|
||||
|
||||
<xs:attributeGroup name="b">
|
||||
<xs:attribute name="b" type="string" />
|
||||
</xs:attributeGroup>
|
||||
|
||||
<xs:attributeGroup name="a">
|
||||
<xs:attribute name="a" type="string" />
|
||||
<xs:attributeGroup ref="ns:b" />
|
||||
</xs:attributeGroup>
|
||||
|
||||
<xs:complexType name="dummy">
|
||||
<xs:sequence>
|
||||
<xs:element name="foo" type="string" />
|
||||
</xs:sequence>
|
||||
<xs:attributeGroup ref="ns:a" />
|
||||
<xs:attributeGroup ref="ns:c" />
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
</wsdl:types>
|
||||
|
||||
<!-- Below is a shortened copy of the test.wsdl, doesn't matter, only the types matter -->
|
||||
|
||||
<message name="AddRequest">
|
||||
<part name="x" type="xs:double" />
|
||||
</message>
|
||||
|
||||
<portType name="TestServicePortType">
|
||||
<operation name="Add">
|
||||
<input message="tns:AddRequest" />
|
||||
</operation>
|
||||
</portType>
|
||||
|
||||
<binding name="TestServiceBinding" type="tns:TestServicePortType">
|
||||
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
|
||||
<operation name="Add">
|
||||
<soap:operation soapAction="Add" style="rpc" />
|
||||
<input>
|
||||
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
|
||||
</input>
|
||||
</operation>
|
||||
</binding>
|
||||
|
||||
<service name="TestService">
|
||||
<port name="TestServicePort" binding="tns:TestServiceBinding">
|
||||
<soap:address location="http://linuxsrv.home/~dmitry/soap/soap_server.php" />
|
||||
</port>
|
||||
</service>
|
||||
|
||||
</wsdl:definitions>
|
Loading…
Add table
Add a link
Reference in a new issue