Skip to content

Implement GH-15711: Allow SoapClient to use the backing value during response serialization #15803

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
26 changes: 25 additions & 1 deletion ext/soap/php_encoding.c
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,30 @@ static zend_string *get_serialization_string_from_zval(zval *data)
}
}

static zend_long get_serialization_long_from_zval(zval *data)
{
switch (Z_TYPE_P(data)) {
case IS_OBJECT:
if (Z_OBJCE_P(data)->ce_flags & ZEND_ACC_ENUM) {
if (UNEXPECTED(Z_OBJCE_P(data)->enum_backing_type != IS_LONG)) {
if (Z_OBJCE_P(data)->enum_backing_type == IS_UNDEF) {
zend_value_error("Non-backed enums have no default serialization");
} else {
zend_value_error("String-backed enum cannot be serialized as int");
}
return 0;
} else {
zval *value = zend_enum_fetch_case_value(Z_OBJ_P(data));
ZEND_ASSERT(Z_TYPE_P(value) == IS_LONG);
return Z_LVAL_P(value);
}
}
ZEND_FALLTHROUGH;
default:
return zval_get_long(data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this guaranteed to be an integer string?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. It'll throw if that's not the case.

}
}

static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
{
xmlNodePtr ret, text;
Expand Down Expand Up @@ -1075,7 +1099,7 @@ static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNode
snprintf(s, sizeof(s), "%0.0F",floor(Z_DVAL_P(data)));
xmlNodeSetContent(ret, BAD_CAST(s));
} else {
zend_string *str = zend_long_to_str(zval_get_long(data));
zend_string *str = zend_long_to_str(get_serialization_long_from_zval(data));
xmlNodeSetContentLen(ret, BAD_CAST(ZSTR_VAL(str)), ZSTR_LEN(str));
zend_string_release_ex(str, 0);
}
Expand Down
48 changes: 35 additions & 13 deletions ext/soap/tests/gh15711.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0
--FILE--
<?php

enum TestBackedEnum: string
enum StringBackedEnum: string
{
case First = 'BackingValue1';
case Second = 'BackingValue2';
Expand All @@ -16,7 +16,13 @@ enum TestBackedEnum: string
case Fifth = 'BackingValue5';
}

enum TestNonBackedEnum
enum IntBackedEnum: int
{
case First = 1;
case Second = 2;
}

enum NonBackedEnum
{
case First;
}
Expand All @@ -32,11 +38,13 @@ $client = new TestSoapClient('ext/soap/tests/gh15711.wsdl', ['classmap' => ['boo
echo "--- Test with backed enum ---\n";

$book = new stdClass();
$book->base64 = TestBackedEnum::First;
$book->string = TestBackedEnum::Second;
$book->any = TestBackedEnum::Third;
$book->hexbin = TestBackedEnum::Fourth;
$book->nmtokens = TestBackedEnum::Fifth;
$book->base64 = StringBackedEnum::First;
$book->string = StringBackedEnum::Second;
$book->any = StringBackedEnum::Third;
$book->hexbin = StringBackedEnum::Fourth;
$book->nmtokens = StringBackedEnum::Fifth;
$book->integer = IntBackedEnum::First;
$book->short = IntBackedEnum::Second;

try {
$client->dotest($book);
Expand All @@ -45,12 +53,24 @@ try {
echo "--- Test with non-backed enum ---\n";

$book = new stdClass();
$book->base64 = TestNonBackedEnum::First;
$book->string = TestNonBackedEnum::First;
$book->any = TestNonBackedEnum::First;
$book->hexbin = TestNonBackedEnum::First;
$book->nmtokens = TestNonBackedEnum::First;
$book->base64 = NonBackedEnum::First;
$book->string = NonBackedEnum::First;
$book->any = NonBackedEnum::First;
$book->hexbin = NonBackedEnum::First;
$book->nmtokens = NonBackedEnum::First;
$book->integer = NonBackedEnum::First;
$book->short = NonBackedEnum::First;

try {
$client->dotest($book);
} catch (ValueError $e) {
echo "ValueError: ", $e->getMessage(), "\n";
}

echo "--- Test with mismatched enum backing type ---\n";

$book->integer = StringBackedEnum::First;
$book->short = StringBackedEnum::First;
try {
$client->dotest($book);
} catch (ValueError $e) {
Expand All @@ -61,6 +81,8 @@ try {
--EXPECT--
--- Test with backed enum ---
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.nothing.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:dotest><dotestReturn xsi:type="ns1:book"><base64 xsi:type="xsd:base64Binary">QmFja2luZ1ZhbHVlMQ==</base64><string xsi:type="xsd:string">BackingValue2</string><any xsi:type="xsd:any"><name xsi:type="xsd:string">Third</name><value xsi:type="xsd:string">BackingValue3</value></any><hexbin xsi:type="xsd:hexBinary">4261636B696E6756616C756534</hexbin><nmtokens>BackingValue5</nmtokens></dotestReturn></ns1:dotest></SOAP-ENV:Body></SOAP-ENV:Envelope>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.nothing.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:dotest><dotestReturn xsi:type="ns1:book"><base64 xsi:type="xsd:base64Binary">QmFja2luZ1ZhbHVlMQ==</base64><string xsi:type="xsd:string">BackingValue2</string><any xsi:type="xsd:any"><name xsi:type="xsd:string">Third</name><value xsi:type="xsd:string">BackingValue3</value></any><hexbin xsi:type="xsd:hexBinary">4261636B696E6756616C756534</hexbin><nmtokens>BackingValue5</nmtokens><integer xsi:type="xsd:integer">1</integer><short xsi:type="xsd:short">2</short></dotestReturn></ns1:dotest></SOAP-ENV:Body></SOAP-ENV:Envelope>
--- Test with non-backed enum ---
ValueError: Non-backed enums have no default serialization
--- Test with mismatched enum backing type ---
ValueError: String-backed enum cannot be serialized as int
2 changes: 2 additions & 0 deletions ext/soap/tests/gh15711.wsdl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<xsd:element name="any" type="xsd:any"/>
<xsd:element name="hexbin" type="xsd:hexBinary"/>
<xsd:element name="nmtokens" type="xsd:NMTOKENS"/>
<xsd:element name="integer" type="xsd:integer"/>
<xsd:element name="short" type="xsd:short"/>
</xsd:all>
</xsd:complexType>
</xsd:schema>
Expand Down
Loading