From 1fd15d425417e091f2ef1a479d7376a11c7126ff Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Sun, 12 Jul 2026 06:45:34 +0800 Subject: [PATCH] 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 --- NEWS | 2 ++ ext/soap/php_encoding.c | 8 +++++- ext/soap/tests/hexbin_odd_length.phpt | 37 +++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 ext/soap/tests/hexbin_odd_length.phpt diff --git a/NEWS b/NEWS index f40c6dfd8da6..190c6c16a935 100644 --- a/NEWS +++ b/NEWS @@ -78,6 +78,8 @@ PHP NEWS - SOAP: . Fixed bug GH-22585 (OOM on bailout with uninitialized do_request() parameters). (David Carlier) + . Fixed xsd:hexBinary decoding to reject odd-length values instead of + silently truncating the last nibble. (Weilin Du) - Standard: . Fixed sleep() and usleep() to reject values that overflow the underlying diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index e474798df6da..301cdd8588b4 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -766,6 +766,7 @@ static zval *to_zval_base64(zval *ret, encodeTypePtr type, xmlNodePtr data) static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data) { zend_string *str; + size_t content_len; size_t i, j; unsigned char c; @@ -778,7 +779,12 @@ static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data) soap_error0(E_ERROR, "Encoding: Violation of encoding rules"); return ret; } - str = zend_string_alloc(strlen((char*)data->children->content) / 2, 0); + content_len = strlen((char*) data->children->content); + if (content_len % 2 != 0) { + soap_error0(E_ERROR, "Encoding: Violation of encoding rules"); + return ret; + } + str = zend_string_alloc(content_len / 2, 0); for (i = j = 0; i < ZSTR_LEN(str); i++) { c = data->children->content[j++]; if (c >= '0' && c <= '9') { diff --git a/ext/soap/tests/hexbin_odd_length.phpt b/ext/soap/tests/hexbin_odd_length.phpt new file mode 100644 index 000000000000..bfe84ab643db --- /dev/null +++ b/ext/soap/tests/hexbin_odd_length.phpt @@ -0,0 +1,37 @@ +--TEST-- +SOAP rejects odd-length xsd:hexBinary values +--EXTENSIONS-- +soap +--FILE-- + + + + + ABC + + + +XML; + } +} + +$client = new TestSoapClient(null, [ + 'location' => 'test://', + 'uri' => 'urn:test', + 'exceptions' => true, +]); + +try { + var_dump(bin2hex($client->test())); +} catch (SoapFault $e) { + echo $e->faultstring, "\n"; +} +?> +--EXPECT-- +SOAP-ERROR: Encoding: Violation of encoding rules