Skip to content

Commit

Permalink
Declare SoapVar properties
Browse files Browse the repository at this point in the history
  • Loading branch information
nikic committed Aug 19, 2021
1 parent 030bb36 commit c58c926
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 53 deletions.
79 changes: 42 additions & 37 deletions ext/soap/php_encoding.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,22 +379,21 @@ static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xml
}

/* Special handling of class SoapVar */
if (data &&
Z_TYPE_P(data) == IS_OBJECT &&
Z_OBJCE_P(data) == soap_var_class_entry) {
zval *ztype, *zdata, *zns, *zstype, *zname, *znamens;
if (data && Z_TYPE_P(data) == IS_OBJECT && Z_OBJCE_P(data) == soap_var_class_entry) {
encodePtr enc = NULL;
HashTable *ht = Z_OBJPROP_P(data);

if ((ztype = zend_hash_str_find_deref(ht, "enc_type", sizeof("enc_type")-1)) == NULL ||
Z_TYPE_P(ztype) != IS_LONG) {
zval *ztype = Z_VAR_ENC_TYPE_P(data);
ZVAL_DEREF(ztype);
if (Z_TYPE_P(ztype) != IS_LONG) {
soap_error0(E_ERROR, "Encoding: SoapVar has no 'enc_type' property");
}

if ((zstype = zend_hash_str_find_deref(ht, "enc_stype", sizeof("enc_stype")-1)) != NULL &&
Z_TYPE_P(zstype) == IS_STRING) {
if ((zns = zend_hash_str_find_deref(ht, "enc_ns", sizeof("enc_ns")-1)) != NULL &&
Z_TYPE_P(zns) == IS_STRING) {
zval *zstype = Z_VAR_ENC_STYPE_P(data);
ZVAL_DEREF(zstype);
if (Z_TYPE_P(zstype) == IS_STRING) {
zval *zns = Z_VAR_ENC_NS_P(data);
ZVAL_DEREF(zns);
if (Z_TYPE_P(zns) == IS_STRING) {
enc = get_encoder(SOAP_GLOBAL(sdl), Z_STRVAL_P(zns), Z_STRVAL_P(zstype));
} else {
zns = NULL;
Expand All @@ -404,10 +403,10 @@ static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xml
smart_str nscat = {0};

if (zns != NULL) {
smart_str_appendl(&nscat, Z_STRVAL_P(zns), Z_STRLEN_P(zns));
smart_str_append(&nscat, Z_STR_P(zns));
smart_str_appendc(&nscat, ':');
}
smart_str_appendl(&nscat, Z_STRVAL_P(zstype), Z_STRLEN_P(zstype));
smart_str_append(&nscat, Z_STR_P(zstype));
smart_str_0(&nscat);
enc = zend_hash_find_ptr(SOAP_GLOBAL(typemap), nscat.s);
smart_str_free(&nscat);
Expand All @@ -420,27 +419,33 @@ static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xml
enc = encode;
}

zdata = zend_hash_str_find_deref(ht, "enc_value", sizeof("enc_value")-1);
zval *zdata = Z_VAR_ENC_VALUE_P(data);
ZVAL_DEREF(zdata);
node = master_to_xml(enc, zdata, style, parent);

if (style == SOAP_ENCODED || (SOAP_GLOBAL(sdl) && encode != enc)) {
if ((zstype = zend_hash_str_find_deref(ht, "enc_stype", sizeof("enc_stype")-1)) != NULL &&
Z_TYPE_P(zstype) == IS_STRING) {
if ((zns = zend_hash_str_find_deref(ht, "enc_ns", sizeof("enc_ns")-1)) != NULL &&
Z_TYPE_P(zns) == IS_STRING) {
zval *zstype = Z_VAR_ENC_STYPE_P(data);
ZVAL_DEREF(zstype);
if (Z_TYPE_P(zstype) == IS_STRING) {
zval *zns = Z_VAR_ENC_NS_P(data);
ZVAL_DEREF(zns);
if (Z_TYPE_P(zns) == IS_STRING) {
set_ns_and_type_ex(node, Z_STRVAL_P(zns), Z_STRVAL_P(zstype));
} else {
set_ns_and_type_ex(node, NULL, Z_STRVAL_P(zstype));
}
}
}

if ((zname = zend_hash_str_find_deref(ht, "enc_name", sizeof("enc_name")-1)) != NULL &&
Z_TYPE_P(zname) == IS_STRING) {
zval *zname = Z_VAR_ENC_NAME_P(data);
ZVAL_DEREF(zname);
if (Z_TYPE_P(zname) == IS_STRING) {
xmlNodeSetName(node, BAD_CAST(Z_STRVAL_P(zname)));
}
if ((znamens = zend_hash_str_find_deref(ht, "enc_namens", sizeof("enc_namens")-1)) != NULL &&
Z_TYPE_P(znamens) == IS_STRING) {

zval *znamens = Z_VAR_ENC_NAMENS_P(data);
ZVAL_DEREF(znamens);
if (Z_TYPE_P(znamens) == IS_STRING) {
xmlNsPtr nsp = encode_add_ns(node, Z_STRVAL_P(znamens));
xmlSetNs(node, nsp);
}
Expand Down Expand Up @@ -2814,14 +2819,13 @@ static zval *guess_zval_convert(zval *ret, encodeTypePtr type, xmlNodePtr data)
xmlNsPtr nsptr;

object_init_ex(&soapvar, soap_var_class_entry);
add_property_long(&soapvar, "enc_type", enc->details.type);
Z_TRY_DELREF_P(ret);
add_property_zval(&soapvar, "enc_value", ret);
ZVAL_LONG(Z_VAR_ENC_TYPE_P(&soapvar), enc->details.type);
ZVAL_COPY_VALUE(Z_VAR_ENC_VALUE_P(&soapvar), ret);
parse_namespace(type_name, &cptype, &ns);
nsptr = xmlSearchNs(data->doc, data, BAD_CAST(ns));
add_property_string(&soapvar, "enc_stype", cptype);
ZVAL_STRING(Z_VAR_ENC_STYPE_P(&soapvar), cptype);
if (nsptr) {
add_property_string(&soapvar, "enc_ns", (char*)nsptr->href);
ZVAL_STRING(Z_VAR_ENC_NS_P(&soapvar), (char*)nsptr->href);
}
efree(cptype);
if (ns) {efree(ns);}
Expand Down Expand Up @@ -3494,24 +3498,25 @@ static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *type)
ZVAL_DEREF(tmp);
if (Z_TYPE_P(tmp) == IS_OBJECT &&
Z_OBJCE_P(tmp) == soap_var_class_entry) {
zval *ztype;

if ((ztype = zend_hash_str_find_deref(Z_OBJPROP_P(tmp), "enc_type", sizeof("enc_type")-1)) == NULL ||
Z_TYPE_P(ztype) != IS_LONG) {
zval *ztype = Z_VAR_ENC_TYPE_P(tmp);
ZVAL_DEREF(ztype);
if (Z_TYPE_P(ztype) != IS_LONG) {
soap_error0(E_ERROR, "Encoding: SoapVar has no 'enc_type' property");
}
cur_type = Z_LVAL_P(ztype);

if ((ztype = zend_hash_str_find_deref(Z_OBJPROP_P(tmp), "enc_stype", sizeof("enc_stype")-1)) != NULL &&
Z_TYPE_P(ztype) == IS_STRING) {
cur_stype = Z_STRVAL_P(ztype);
zval *zstype = Z_VAR_ENC_STYPE_P(tmp);
ZVAL_DEREF(zstype);
if (Z_TYPE_P(zstype) == IS_STRING) {
cur_stype = Z_STRVAL_P(zstype);
} else {
cur_stype = NULL;
}

if ((ztype = zend_hash_str_find_deref(Z_OBJPROP_P(tmp), "enc_ns", sizeof("enc_ns")-1)) != NULL &&
Z_TYPE_P(ztype) == IS_STRING) {
cur_ns = Z_STRVAL_P(ztype);
zval *zns = Z_VAR_ENC_NS_P(tmp);
ZVAL_DEREF(zns);
if (Z_TYPE_P(zns) == IS_STRING) {
cur_ns = Z_STRVAL_P(zns);
} else {
cur_ns = NULL;
}
Expand Down
7 changes: 7 additions & 0 deletions ext/soap/php_encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@
#define UNKNOWN_TYPE 999998
#define END_KNOWN_TYPES 999999

#define Z_VAR_ENC_TYPE_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 0)
#define Z_VAR_ENC_VALUE_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 1)
#define Z_VAR_ENC_STYPE_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 2)
#define Z_VAR_ENC_NS_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 3)
#define Z_VAR_ENC_NAME_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 4)
#define Z_VAR_ENC_NAMENS_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 5)

struct _encodeType {
int type;
char *type_str;
Expand Down
27 changes: 13 additions & 14 deletions ext/soap/soap.c
Original file line number Diff line number Diff line change
Expand Up @@ -673,40 +673,39 @@ PHP_METHOD(SoapVar, __construct)
zval *data, *this_ptr;
zend_long type;
bool type_is_null = 1;
char *stype = NULL, *ns = NULL, *name = NULL, *namens = NULL;
size_t stype_len = 0, ns_len = 0, name_len = 0, namens_len = 0;
zend_string *stype = NULL, *ns = NULL, *name = NULL, *namens = NULL;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "z!l!|s!s!s!s!", &data, &type, &type_is_null, &stype, &stype_len, &ns, &ns_len, &name, &name_len, &namens, &namens_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z!l!|S!S!S!S!", &data, &type, &type_is_null, &stype, &ns, &name, &namens) == FAILURE) {
RETURN_THROWS();
}

this_ptr = ZEND_THIS;
if (type_is_null) {
add_property_long(this_ptr, "enc_type", UNKNOWN_TYPE);
ZVAL_LONG(Z_VAR_ENC_TYPE_P(this_ptr), UNKNOWN_TYPE);
} else {
if (zend_hash_index_exists(&SOAP_GLOBAL(defEncIndex), type)) {
add_property_long(this_ptr, "enc_type", type);
ZVAL_LONG(Z_VAR_ENC_TYPE_P(this_ptr), type);
} else {
zend_argument_value_error(2, "is not a valid encoding");
RETURN_THROWS();
}
}

if (data) {
add_property_zval(this_ptr, "enc_value", data);
ZVAL_COPY(Z_VAR_ENC_VALUE_P(this_ptr), data);
}

if (stype && stype_len > 0) {
add_property_stringl(this_ptr, "enc_stype", stype, stype_len);
if (stype && ZSTR_LEN(stype) != 0) {
ZVAL_STR_COPY(Z_VAR_ENC_STYPE_P(this_ptr), stype);
}
if (ns && ns_len > 0) {
add_property_stringl(this_ptr, "enc_ns", ns, ns_len);
if (ns && ZSTR_LEN(ns) != 0) {
ZVAL_STR_COPY(Z_VAR_ENC_NS_P(this_ptr), ns);
}
if (name && name_len > 0) {
add_property_stringl(this_ptr, "enc_name", name, name_len);
if (name && ZSTR_LEN(name) != 0) {
ZVAL_STR_COPY(Z_VAR_ENC_NAME_P(this_ptr), name);
}
if (namens && namens_len > 0) {
add_property_stringl(this_ptr, "enc_namens", namens, namens_len);
if (namens && ZSTR_LEN(namens) != 0) {
ZVAL_STR_COPY(Z_VAR_ENC_NAMENS_P(this_ptr), namens);
}
}
/* }}} */
Expand Down
7 changes: 7 additions & 0 deletions ext/soap/soap.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ public function __toString(): string {}

class SoapVar
{
public int $enc_type;
public mixed $enc_value = null;
public ?string $enc_stype = null;
public ?string $enc_ns = null;
public ?string $enc_name = null;
public ?string $enc_namens = null;

public function __construct(mixed $data, ?int $encoding, ?string $typeName = null, ?string $typeNamespace = null, ?string $nodeName = null, ?string $nodeNamespace = null) {}
}

Expand Down
38 changes: 37 additions & 1 deletion ext/soap/soap_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: a5baf303718efbc6fa5700de62fe8f33e6be0874 */
* Stub hash: 6e48f3873213091cf629f9dc7f2c7285ffcf23eb */

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_use_soap_error_handler, 0, 0, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, enable, _IS_BOOL, 0, "true")
Expand Down Expand Up @@ -282,6 +282,42 @@ static zend_class_entry *register_class_SoapVar(void)
INIT_CLASS_ENTRY(ce, "SoapVar", class_SoapVar_methods);
class_entry = zend_register_internal_class_ex(&ce, NULL);

zval property_enc_type_default_value;
ZVAL_UNDEF(&property_enc_type_default_value);
zend_string *property_enc_type_name = zend_string_init("enc_type", sizeof("enc_type") - 1, 1);
zend_declare_typed_property(class_entry, property_enc_type_name, &property_enc_type_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
zend_string_release(property_enc_type_name);

zval property_enc_value_default_value;
ZVAL_NULL(&property_enc_value_default_value);
zend_string *property_enc_value_name = zend_string_init("enc_value", sizeof("enc_value") - 1, 1);
zend_declare_typed_property(class_entry, property_enc_value_name, &property_enc_value_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY));
zend_string_release(property_enc_value_name);

zval property_enc_stype_default_value;
ZVAL_NULL(&property_enc_stype_default_value);
zend_string *property_enc_stype_name = zend_string_init("enc_stype", sizeof("enc_stype") - 1, 1);
zend_declare_typed_property(class_entry, property_enc_stype_name, &property_enc_stype_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL));
zend_string_release(property_enc_stype_name);

zval property_enc_ns_default_value;
ZVAL_NULL(&property_enc_ns_default_value);
zend_string *property_enc_ns_name = zend_string_init("enc_ns", sizeof("enc_ns") - 1, 1);
zend_declare_typed_property(class_entry, property_enc_ns_name, &property_enc_ns_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL));
zend_string_release(property_enc_ns_name);

zval property_enc_name_default_value;
ZVAL_NULL(&property_enc_name_default_value);
zend_string *property_enc_name_name = zend_string_init("enc_name", sizeof("enc_name") - 1, 1);
zend_declare_typed_property(class_entry, property_enc_name_name, &property_enc_name_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL));
zend_string_release(property_enc_name_name);

zval property_enc_namens_default_value;
ZVAL_NULL(&property_enc_namens_default_value);
zend_string *property_enc_namens_name = zend_string_init("enc_namens", sizeof("enc_namens") - 1, 1);
zend_declare_typed_property(class_entry, property_enc_namens_name, &property_enc_namens_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL));
zend_string_release(property_enc_namens_name);

return class_entry;
}

Expand Down
6 changes: 5 additions & 1 deletion ext/soap/tests/bugs/bug73237.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ object(stdClass)#2 (1) {
["queryLocator"]=>
NULL
["records"]=>
object(SoapVar)#6 (4) {
object(SoapVar)#6 (6) {
["enc_type"]=>
int(0)
["enc_value"]=>
Expand Down Expand Up @@ -58,6 +58,10 @@ object(stdClass)#2 (1) {
string(13) "genericObject"
["enc_ns"]=>
string(27) "urn:object.test.example.org"
["enc_name"]=>
NULL
["enc_namens"]=>
NULL
}
["size"]=>
string(1) "1"
Expand Down

0 comments on commit c58c926

Please sign in to comment.