Skip to content

Commit d1daad1

Browse files
committed
ext/soap: Improve SOAP scalar decoding error messages
1 parent 1fd15d4 commit d1daad1

7 files changed

Lines changed: 89 additions & 17 deletions

File tree

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ PHP NEWS
8080
do_request() parameters). (David Carlier)
8181
. Fixed xsd:hexBinary decoding to reject odd-length values instead of
8282
silently truncating the last nibble. (Weilin Du)
83+
. Made SOAP scalar decoding errors report the affected type instead of the
84+
generic "Violation of encoding rules" message. (Weilin Du)
8385

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

ext/soap/php_encoding.c

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,26 @@ static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodeP
8282
static zval *guess_zval_convert(zval *ret, encodeTypePtr type, xmlNodePtr data);
8383
static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
8484

85+
static zend_always_inline const char *soap_type_name(encodeTypePtr type)
86+
{
87+
return (type && type->type_str) ? type->type_str : "unknown";
88+
}
89+
90+
static zend_always_inline void soap_encoding_error_invalid_node(encodeTypePtr type)
91+
{
92+
soap_error1(E_ERROR, "Encoding: Type '%s' value must contain a single text or CDATA node", soap_type_name(type));
93+
}
94+
95+
static zend_always_inline void soap_encoding_error_invalid_value(encodeTypePtr type)
96+
{
97+
soap_error1(E_ERROR, "Encoding: Invalid value for type '%s'", soap_type_name(type));
98+
}
99+
100+
static zend_always_inline void soap_encoding_error_invalid_hex_length(encodeTypePtr type)
101+
{
102+
soap_error1(E_ERROR, "Encoding: Type '%s' value must contain an even number of hexadecimal digits", soap_type_name(type));
103+
}
104+
85105
static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *out_type);
86106

87107
static xmlNodePtr check_and_resolve_href(xmlNodePtr data);
@@ -660,7 +680,7 @@ static zval *to_zval_string(zval *ret, encodeTypePtr type, xmlNodePtr data)
660680
} else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
661681
ZVAL_STRING(ret, (char*)data->children->content);
662682
} else {
663-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
683+
soap_encoding_error_invalid_node(type);
664684
}
665685
} else {
666686
ZVAL_EMPTY_STRING(ret);
@@ -693,7 +713,7 @@ static zval *to_zval_stringr(zval *ret, encodeTypePtr type, xmlNodePtr data)
693713
} else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
694714
ZVAL_STRING(ret, (char*)data->children->content);
695715
} else {
696-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
716+
soap_encoding_error_invalid_node(type);
697717
}
698718
} else {
699719
ZVAL_EMPTY_STRING(ret);
@@ -726,7 +746,7 @@ static zval *to_zval_stringc(zval *ret, encodeTypePtr type, xmlNodePtr data)
726746
} else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
727747
ZVAL_STRING(ret, (char*)data->children->content);
728748
} else {
729-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
749+
soap_encoding_error_invalid_node(type);
730750
}
731751
} else {
732752
ZVAL_EMPTY_STRING(ret);
@@ -755,7 +775,7 @@ static zval *to_zval_base64(zval *ret, encodeTypePtr type, xmlNodePtr data)
755775
}
756776
ZVAL_STR(ret, str);
757777
} else {
758-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
778+
soap_encoding_error_invalid_node(type);
759779
}
760780
} else {
761781
ZVAL_EMPTY_STRING(ret);
@@ -776,12 +796,12 @@ static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data)
776796
if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
777797
whiteSpace_collapse(data->children->content);
778798
} else if (data->children->type != XML_CDATA_SECTION_NODE || data->children->next != NULL) {
779-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
799+
soap_encoding_error_invalid_node(type);
780800
return ret;
781801
}
782802
content_len = strlen((char*) data->children->content);
783803
if (content_len % 2 != 0) {
784-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
804+
soap_encoding_error_invalid_hex_length(type);
785805
return ret;
786806
}
787807
str = zend_string_alloc(content_len / 2, 0);
@@ -794,7 +814,7 @@ static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data)
794814
} else if (c >= 'A' && c <= 'F') {
795815
ZSTR_VAL(str)[i] = (c - 'A' + 10) << 4;
796816
} else {
797-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
817+
soap_encoding_error_invalid_value(type);
798818
}
799819
c = data->children->content[j++];
800820
if (c >= '0' && c <= '9') {
@@ -804,7 +824,7 @@ static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data)
804824
} else if (c >= 'A' && c <= 'F') {
805825
ZSTR_VAL(str)[i] |= c - 'A' + 10;
806826
} else {
807-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
827+
soap_encoding_error_invalid_value(type);
808828
}
809829
}
810830
ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
@@ -1025,11 +1045,11 @@ static zval *to_zval_double(zval *ret, encodeTypePtr type, xmlNodePtr data)
10251045
} else if (strncasecmp((char*)data->children->content, "-INF", sizeof("-INF")-1) == 0) {
10261046
ZVAL_DOUBLE(ret, -php_get_inf());
10271047
} else {
1028-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1048+
soap_encoding_error_invalid_value(type);
10291049
}
10301050
}
10311051
} else {
1032-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1052+
soap_encoding_error_invalid_node(type);
10331053
}
10341054
} else {
10351055
ZVAL_NULL(ret);
@@ -1058,10 +1078,10 @@ static zval *to_zval_long(zval *ret, encodeTypePtr type, xmlNodePtr data)
10581078
ZVAL_DOUBLE(ret, dval);
10591079
break;
10601080
default:
1061-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1081+
soap_encoding_error_invalid_value(type);
10621082
}
10631083
} else {
1064-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1084+
soap_encoding_error_invalid_node(type);
10651085
}
10661086
} else {
10671087
ZVAL_NULL(ret);
@@ -1127,7 +1147,7 @@ static zval *to_zval_bool(zval *ret, encodeTypePtr type, xmlNodePtr data)
11271147
}
11281148
if (data->children->type != XML_TEXT_NODE || data->children->next != NULL) {
11291149
// TODO Convert to exception?
1130-
soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1150+
soap_encoding_error_invalid_node(type);
11311151
}
11321152

11331153
whiteSpace_collapse(data->children->content);

ext/soap/tests/bugs/bug39832.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ $x->handle($HTTP_RAW_POST_DATA);
2626
?>
2727
--EXPECT--
2828
<?xml version="1.0" encoding="UTF-8"?>
29-
<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>
29+
<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 'PriorityType'</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>

ext/soap/tests/hexbin_odd_length.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ try {
3434
}
3535
?>
3636
--EXPECT--
37-
SOAP-ERROR: Encoding: Violation of encoding rules
37+
SOAP-ERROR: Encoding: Type 'hexBinary' value must contain an even number of hexadecimal digits
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
SOAP reports specific scalar encoding errors
3+
--EXTENSIONS--
4+
soap
5+
--FILE--
6+
<?php
7+
class ScalarErrorClient extends SoapClient {
8+
public string $response;
9+
10+
public function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string {
11+
return $this->response;
12+
}
13+
}
14+
15+
function soap_response(string $type, string $value): string {
16+
return <<<XML
17+
<?xml version="1.0" encoding="UTF-8"?>
18+
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
19+
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
20+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
21+
<SOAP-ENV:Body>
22+
<ns1:testResponse xmlns:ns1="urn:test">
23+
<return xsi:type="$type">$value</return>
24+
</ns1:testResponse>
25+
</SOAP-ENV:Body>
26+
</SOAP-ENV:Envelope>
27+
XML;
28+
}
29+
30+
function run_case(string $label, string $type, string $value): void {
31+
$client = new ScalarErrorClient(null, [
32+
'location' => 'test://',
33+
'uri' => 'urn:test',
34+
'exceptions' => true,
35+
]);
36+
$client->response = soap_response($type, $value);
37+
38+
try {
39+
$client->__soapCall('test', []);
40+
} catch (SoapFault $e) {
41+
echo $label, ': ', $e->faultstring, "\n";
42+
}
43+
}
44+
45+
run_case('double', 'xsd:double', 'abc');
46+
run_case('long', 'xsd:long', 'abc');
47+
?>
48+
--EXPECT--
49+
double: SOAP-ERROR: Encoding: Invalid value for type 'double'
50+
long: SOAP-ERROR: Encoding: Invalid value for type 'long'

ext/soap/tests/soap12/T27.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ include "soap12-test.inc";
2525
?>
2626
--EXPECT--
2727
<?xml version="1.0" encoding="UTF-8"?>
28-
<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>
28+
<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>

ext/soap/tests/soap12/T58.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ include "soap12-test.inc";
2424
?>
2525
--EXPECT--
2626
<?xml version="1.0" encoding="UTF-8"?>
27-
<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>
27+
<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>

0 commit comments

Comments
 (0)