Skip to content

Commit 1fd15d4

Browse files
authored
ext/soap: Fix SOAP xsd:hexBinary odd-length decoding (#22698)
xsd:hexBinary values must contain an even number of hexadecimal digits. However, previously we allocated strlen(content) / 2 bytes and decoded only complete byte pairs. As a result, an odd-length value such as ABC was accepted as ab (what...?), silently ignoring the trailing nibble. Lets reject odd-length xsd:hexBinary values instead and throw an Error here which makes better sense. The error message is copied from other decoding errors. (I think in the future, we can make the decoding error message more useful, in bulk.) This is in master as a stricter parsing PR
1 parent 838a9c2 commit 1fd15d4

3 files changed

Lines changed: 46 additions & 1 deletion

File tree

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ PHP NEWS
7878
- SOAP:
7979
. Fixed bug GH-22585 (OOM on bailout with uninitialized
8080
do_request() parameters). (David Carlier)
81+
. Fixed xsd:hexBinary decoding to reject odd-length values instead of
82+
silently truncating the last nibble. (Weilin Du)
8183

8284
- Standard:
8385
. Fixed sleep() and usleep() to reject values that overflow the underlying

ext/soap/php_encoding.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,7 @@ static zval *to_zval_base64(zval *ret, encodeTypePtr type, xmlNodePtr data)
766766
static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data)
767767
{
768768
zend_string *str;
769+
size_t content_len;
769770
size_t i, j;
770771
unsigned char c;
771772

@@ -778,7 +779,12 @@ static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data)
778779
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
779780
return ret;
780781
}
781-
str = zend_string_alloc(strlen((char*)data->children->content) / 2, 0);
782+
content_len = strlen((char*) data->children->content);
783+
if (content_len % 2 != 0) {
784+
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
785+
return ret;
786+
}
787+
str = zend_string_alloc(content_len / 2, 0);
782788
for (i = j = 0; i < ZSTR_LEN(str); i++) {
783789
c = data->children->content[j++];
784790
if (c >= '0' && c <= '9') {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
SOAP rejects odd-length xsd:hexBinary values
3+
--EXTENSIONS--
4+
soap
5+
--FILE--
6+
<?php
7+
class TestSoapClient extends SoapClient {
8+
public function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string {
9+
return <<<'XML'
10+
<?xml version="1.0" encoding="UTF-8"?>
11+
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
12+
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
13+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
14+
<SOAP-ENV:Body>
15+
<ns1:testResponse xmlns:ns1="urn:test">
16+
<return xsi:type="xsd:hexBinary">ABC</return>
17+
</ns1:testResponse>
18+
</SOAP-ENV:Body>
19+
</SOAP-ENV:Envelope>
20+
XML;
21+
}
22+
}
23+
24+
$client = new TestSoapClient(null, [
25+
'location' => 'test://',
26+
'uri' => 'urn:test',
27+
'exceptions' => true,
28+
]);
29+
30+
try {
31+
var_dump(bin2hex($client->test()));
32+
} catch (SoapFault $e) {
33+
echo $e->faultstring, "\n";
34+
}
35+
?>
36+
--EXPECT--
37+
SOAP-ERROR: Encoding: Violation of encoding rules

0 commit comments

Comments
 (0)