Skip to content
Merged
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 encoding errors report the affected type or failing operation
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.
. SOAP encoding errors now report the affected type or failing operation in
the error message instead of the generic "Encoding: Violation of encoding
rules" message. Code that compares the exact message may need to be
updated.

- Sodium:
. The password-hashing functions sodium_crypto_pwhash(),
Expand Down
43 changes: 26 additions & 17 deletions ext/soap/php_encoding.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ 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 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 +665,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_error1(E_ERROR, "Encoding: Type '%s' value must contain a single text or CDATA node", soap_type_name(type));
}
} else {
ZVAL_EMPTY_STRING(ret);
Expand Down Expand Up @@ -693,7 +698,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_error1(E_ERROR, "Encoding: Type '%s' value must contain a single text or CDATA node", soap_type_name(type));
}
} else {
ZVAL_EMPTY_STRING(ret);
Expand Down Expand Up @@ -726,7 +731,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_error1(E_ERROR, "Encoding: Type '%s' value must contain a single text or CDATA node", soap_type_name(type));
}
} else {
ZVAL_EMPTY_STRING(ret);
Expand All @@ -745,17 +750,17 @@ static zval *to_zval_base64(zval *ret, encodeTypePtr type, xmlNodePtr data)
whiteSpace_collapse(data->children->content);
str = php_base64_decode(data->children->content, strlen((char*)data->children->content));
if (!str) {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_error1(E_ERROR, "Encoding: Invalid value for type '%s'", soap_type_name(type));
}
ZVAL_STR(ret, str);
} else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
str = php_base64_decode(data->children->content, strlen((char*)data->children->content));
if (!str) {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_error1(E_ERROR, "Encoding: Invalid value for type '%s'", soap_type_name(type));
}
ZVAL_STR(ret, str);
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_error1(E_ERROR, "Encoding: Type '%s' value must contain a single text or CDATA node", soap_type_name(type));
}
} else {
ZVAL_EMPTY_STRING(ret);
Expand All @@ -776,12 +781,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_error1(E_ERROR, "Encoding: Type '%s' value must contain a single text or CDATA node", soap_type_name(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_error1(E_ERROR, "Encoding: Type '%s' value must contain an even number of hexadecimal digits", soap_type_name(type));
return ret;
}
str = zend_string_alloc(content_len / 2, 0);
Expand All @@ -794,7 +799,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_error1(E_ERROR, "Encoding: Invalid value for type '%s'", soap_type_name(type));
}
c = data->children->content[j++];
if (c >= '0' && c <= '9') {
Expand All @@ -804,7 +809,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_error1(E_ERROR, "Encoding: Invalid value for type '%s'", soap_type_name(type));
}
}
ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
Expand Down Expand Up @@ -1025,11 +1030,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_error1(E_ERROR, "Encoding: Invalid value for type '%s'", soap_type_name(type));
}
}
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_error1(E_ERROR, "Encoding: Type '%s' value must contain a single text or CDATA node", soap_type_name(type));
}
} else {
ZVAL_NULL(ret);
Expand Down Expand Up @@ -1058,10 +1063,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_error1(E_ERROR, "Encoding: Invalid value for type '%s'", soap_type_name(type));
}
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_error1(E_ERROR, "Encoding: Type '%s' value must contain a single text or CDATA node", soap_type_name(type));
}
} else {
ZVAL_NULL(ret);
Expand Down Expand Up @@ -1127,7 +1132,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_error1(E_ERROR, "Encoding: Type '%s' value must contain a single text or CDATA node", soap_type_name(type));
}

whiteSpace_collapse(data->children->content);
Expand Down Expand Up @@ -3096,7 +3101,9 @@ static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodeP
}
smart_str_appends(&list, (char*)dummy->children->content);
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_error2(E_ERROR,
"Encoding: Failed to encode list item of type '%s' for list type '%s'",
soap_type_name(&list_enc->details), soap_type_name(enc));
}
xmlUnlinkNode(dummy);
xmlFreeNode(dummy);
Expand Down Expand Up @@ -3138,7 +3145,9 @@ static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodeP
}
smart_str_appends(&list, (char*)dummy->children->content);
} else {
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
soap_error2(E_ERROR,
"Encoding: Failed to encode list item of type '%s' for list type '%s'",
soap_type_name(&list_enc->details), soap_type_name(enc));
}
xmlUnlinkNode(dummy);
xmlFreeNode(dummy);
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
52 changes: 52 additions & 0 deletions ext/soap/tests/scalar_error_messages.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
--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');
run_case('base64Binary node', 'xsd:base64Binary', '<value>abc</value>');
?>
--EXPECT--
double: SOAP-ERROR: Encoding: Invalid value for type 'double'
long: SOAP-ERROR: Encoding: Invalid value for type 'long'
base64Binary node: SOAP-ERROR: Encoding: Type 'base64Binary' value must contain a single text or CDATA node
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>
Loading