Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ PHP NEWS
do_request() parameters). (David Carlier)
. Fixed xsd:hexBinary decoding to reject odd-length values instead of
silently truncating the last nibble. (Weilin Du)
. Made SOAP scalar decoding errors report the affected type instead of the
generic "Violation of encoding rules" message. (Weilin Du)

- Standard:
. Fixed sleep() and usleep() to reject values that overflow the underlying
Expand Down
4 changes: 4 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ PHP 8.6 UPGRADE NOTES
. WSDL/XML Schema parsing now rejects out-of-range integer values for
occurrence constraints and integer restriction facets. Negative minOccurs
and maxOccurs values are rejected as well.
. Scalar decoding errors now report the affected type and specific
validation failure in SoapFault::faultstring instead of the generic
"Encoding: Violation of encoding rules" message. Code that compares the
exact fault string may need to be updated.

- Sodium:
. The password-hashing functions sodium_crypto_pwhash(),
Expand Down
46 changes: 33 additions & 13 deletions ext/soap/php_encoding.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,26 @@ static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodeP
static zval *guess_zval_convert(zval *ret, encodeTypePtr type, xmlNodePtr data);
static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);

static zend_always_inline const char *soap_type_name(encodeTypePtr type)
{
return (type && type->type_str) ? type->type_str : "unknown";
}

static zend_always_inline void soap_encoding_error_invalid_node(encodeTypePtr type)
{
soap_error1(E_ERROR, "Encoding: Type '%s' value must contain a single text or CDATA node", soap_type_name(type));
}

static zend_always_inline void soap_encoding_error_invalid_value(encodeTypePtr type)
{
soap_error1(E_ERROR, "Encoding: Invalid value for type '%s'", soap_type_name(type));
}

static zend_always_inline void soap_encoding_error_invalid_hex_length(encodeTypePtr type)
{
soap_error1(E_ERROR, "Encoding: Type '%s' value must contain an even number of hexadecimal digits", soap_type_name(type));
}

static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *out_type);

static xmlNodePtr check_and_resolve_href(xmlNodePtr data);
Expand Down Expand Up @@ -660,7 +680,7 @@ static zval *to_zval_string(zval *ret, encodeTypePtr type, xmlNodePtr data)
} else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
ZVAL_STRING(ret, (char*)data->children->content);
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_node(type);
}
} else {
ZVAL_EMPTY_STRING(ret);
Expand Down Expand Up @@ -693,7 +713,7 @@ static zval *to_zval_stringr(zval *ret, encodeTypePtr type, xmlNodePtr data)
} else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
ZVAL_STRING(ret, (char*)data->children->content);
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_node(type);
}
} else {
ZVAL_EMPTY_STRING(ret);
Expand Down Expand Up @@ -726,7 +746,7 @@ static zval *to_zval_stringc(zval *ret, encodeTypePtr type, xmlNodePtr data)
} else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
ZVAL_STRING(ret, (char*)data->children->content);
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_node(type);
}
} else {
ZVAL_EMPTY_STRING(ret);
Expand Down Expand Up @@ -755,7 +775,7 @@ static zval *to_zval_base64(zval *ret, encodeTypePtr type, xmlNodePtr data)
}
ZVAL_STR(ret, str);
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_node(type);
}
} else {
ZVAL_EMPTY_STRING(ret);
Expand All @@ -776,12 +796,12 @@ static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data)
if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
whiteSpace_collapse(data->children->content);
} else if (data->children->type != XML_CDATA_SECTION_NODE || data->children->next != NULL) {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_node(type);
return ret;
}
content_len = strlen((char*) data->children->content);
if (content_len % 2 != 0) {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_hex_length(type);
return ret;
}
str = zend_string_alloc(content_len / 2, 0);
Expand All @@ -794,7 +814,7 @@ static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data)
} else if (c >= 'A' && c <= 'F') {
ZSTR_VAL(str)[i] = (c - 'A' + 10) << 4;
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_value(type);
}
c = data->children->content[j++];
if (c >= '0' && c <= '9') {
Expand All @@ -804,7 +824,7 @@ static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data)
} else if (c >= 'A' && c <= 'F') {
ZSTR_VAL(str)[i] |= c - 'A' + 10;
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_value(type);
}
}
ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
Expand Down Expand Up @@ -1025,11 +1045,11 @@ static zval *to_zval_double(zval *ret, encodeTypePtr type, xmlNodePtr data)
} else if (strncasecmp((char*)data->children->content, "-INF", sizeof("-INF")-1) == 0) {
ZVAL_DOUBLE(ret, -php_get_inf());
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_value(type);
}
}
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_node(type);
}
} else {
ZVAL_NULL(ret);
Expand Down Expand Up @@ -1058,10 +1078,10 @@ static zval *to_zval_long(zval *ret, encodeTypePtr type, xmlNodePtr data)
ZVAL_DOUBLE(ret, dval);
break;
default:
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_value(type);
}
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_node(type);
}
} else {
ZVAL_NULL(ret);
Expand Down Expand Up @@ -1127,7 +1147,7 @@ static zval *to_zval_bool(zval *ret, encodeTypePtr type, xmlNodePtr data)
}
if (data->children->type != XML_TEXT_NODE || data->children->next != NULL) {
// TODO Convert to exception?
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_encoding_error_invalid_node(type);
}

whiteSpace_collapse(data->children->content);
Expand Down
2 changes: 1 addition & 1 deletion ext/soap/tests/bugs/bug39832.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ $x->handle($HTTP_RAW_POST_DATA);
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>SOAP-ERROR: Encoding: Violation of encoding rules</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>SOAP-ERROR: Encoding: Invalid value for type 'integer'</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
2 changes: 1 addition & 1 deletion ext/soap/tests/hexbin_odd_length.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ try {
}
?>
--EXPECT--
SOAP-ERROR: Encoding: Violation of encoding rules
SOAP-ERROR: Encoding: Type 'hexBinary' value must contain an even number of hexadecimal digits
50 changes: 50 additions & 0 deletions ext/soap/tests/scalar_error_messages.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
--TEST--
SOAP reports specific scalar encoding errors
--EXTENSIONS--
soap
--FILE--
<?php
class ScalarErrorClient extends SoapClient {
public string $response;

public function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string {
return $this->response;
}
}

function soap_response(string $type, string $value): string {
return <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:testResponse xmlns:ns1="urn:test">
<return xsi:type="$type">$value</return>
</ns1:testResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
XML;
}

function run_case(string $label, string $type, string $value): void {
$client = new ScalarErrorClient(null, [
'location' => 'test://',
'uri' => 'urn:test',
'exceptions' => true,
]);
$client->response = soap_response($type, $value);

try {
$client->__soapCall('test', []);
} catch (SoapFault $e) {
echo $label, ': ', $e->faultstring, "\n";
}
}

run_case('double', 'xsd:double', 'abc');
run_case('long', 'xsd:long', 'abc');
?>
--EXPECT--
double: SOAP-ERROR: Encoding: Invalid value for type 'double'
long: SOAP-ERROR: Encoding: Invalid value for type 'long'
2 changes: 1 addition & 1 deletion ext/soap/tests/soap12/T27.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ include "soap12-test.inc";
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Body><env:Fault><env:Code><env:Value>env:Receiver</env:Value></env:Code><env:Reason><env:Text xml:lang="en">SOAP-ERROR: Encoding: Violation of encoding rules</env:Text></env:Reason></env:Fault></env:Body></env:Envelope>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Body><env:Fault><env:Code><env:Value>env:Receiver</env:Value></env:Code><env:Reason><env:Text xml:lang="en">SOAP-ERROR: Encoding: Type 'string' value must contain a single text or CDATA node</env:Text></env:Reason></env:Fault></env:Body></env:Envelope>
2 changes: 1 addition & 1 deletion ext/soap/tests/soap12/T58.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ include "soap12-test.inc";
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Body><env:Fault><env:Code><env:Value>env:Receiver</env:Value></env:Code><env:Reason><env:Text xml:lang="en">SOAP-ERROR: Encoding: Violation of encoding rules</env:Text></env:Reason></env:Fault></env:Body></env:Envelope>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Body><env:Fault><env:Code><env:Value>env:Receiver</env:Value></env:Code><env:Reason><env:Text xml:lang="en">SOAP-ERROR: Encoding: Type 'int' value must contain a single text or CDATA node</env:Text></env:Reason></env:Fault></env:Body></env:Envelope>