From 965ae10a6a58f2f87f883a473729cdfe5150f248 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 10 Jan 2022 21:48:08 +0100 Subject: [PATCH] improve field name unserialization --- Makefile.frag | 2 +- ion_private.h | 53 ++++++++++++++++++++++--------- tests/unserialize/multifield.phpt | 26 +++++++++++++++ tests/unserialize/sid.phpt | 50 +++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 tests/unserialize/multifield.phpt create mode 100644 tests/unserialize/sid.phpt diff --git a/Makefile.frag b/Makefile.frag index 463c78b..1106dc5 100644 --- a/Makefile.frag +++ b/Makefile.frag @@ -26,4 +26,4 @@ clean-ion: gcov-ion: @rm -rf $@ @mkdir -p $@ - gcovr -j $$(nproc) -sr . --html --html-details --html-title $@ -o $@/index.html -f '.*/(php_)?ion.*' + @gcovr -j $$(nproc) -sr . --html --html-details --html-title $@ -o $@/index.html -f '.*/(php_)?ion.*' 2>/dev/null diff --git a/ion_private.h b/ion_private.h index acb2403..4f49088 100644 --- a/ion_private.h +++ b/ion_private.h @@ -389,6 +389,7 @@ LOCAL void *php_ion_obj_ex(void *obj, ptrdiff_t offset) { php_ion_ ## type *old_obj = php_ion_obj(type, std), \ *new_obj = php_ion_obj(type, create_ion_ ## cname(std->ce)); \ php_ion_ ## type ## _copy(new_obj, old_obj); \ + (void) old_obj; \ return &new_obj->std; \ } #define php_ion_register(type, cname, ...) do { \ @@ -2064,25 +2065,47 @@ LOCAL void php_ion_unserialize_object_iface(php_ion_unserializer *ser, zval *ret } } -LOCAL void php_ion_unserialize_field_name(php_ion_unserializer *ser, zend_string **key) +LOCAL void php_ion_unserialize_field_name_ex(php_ion_unserializer *ser, ION_STRING *name, SID *sid) { - // FIXME: symbol table - ION_STRING name; - ION_CHECK(ion_reader_get_field_name(ser->reader, &name)); - if (!name.length) { + ION_CHECK(ion_reader_get_field_name(ser->reader, name)); + if (!name->length) { ION_SYMBOL *is_ptr; ION_CHECK(ion_reader_get_field_name_symbol(ser->reader, &is_ptr)); if (!ION_SYMBOL_IS_NULL(is_ptr) && is_ptr->value.length) { - name = is_ptr->value; - } else if (is_ptr) { - char buf[MAX_LENGTH_OF_LONG + 1 + 1] = {0}, *end = buf + sizeof(buf) - 1, *ptr; - ptr = zend_print_long_to_buf(end, is_ptr->sid); - *--ptr = '$'; - *key = zend_string_init(ptr, end - ptr, 0); - return; + ION_STRING_ASSIGN(name, &is_ptr->value); + } else { + *sid = is_ptr->sid; + } + } +} + +LOCAL void php_ion_unserialize_field_name(php_ion_unserializer *ser, zend_string **key, bool is_prop) +{ + // FIXME: symbol table + ION_STRING name; + SID sid = UNKNOWN_SID; + char buf[MAX_LENGTH_OF_LONG + 1 + 1] = {0}, *end = buf + sizeof(buf) - 1, *ptr; + + php_ion_unserialize_field_name_ex(ser, &name, &sid); + ION_CATCH(); + + switch (name.length) { + case 0: + ptr = zend_print_long_to_buf(end, sid); + *--ptr = '$'; + *key = zend_string_init(ptr, end - ptr, 0); + break; + case 1: + *key = zend_one_char_string[*name.value]; + break; + default: + if (is_prop) { + *key = zend_string_init_interned((char *) name.value, name.length, 0); + } else { + *key = zend_string_from_ion(&name); } + break; } - *key = zend_string_from_ion(&name); } static void php_ion_unserialize_props(php_ion_unserializer *ser, zval *return_value) @@ -2100,7 +2123,7 @@ static void php_ion_unserialize_props(php_ion_unserializer *ser, zval *return_va } zend_string *key; - php_ion_unserialize_field_name(ser, &key); + php_ion_unserialize_field_name(ser, &key, true); ION_CATCH(); zval zvalue; @@ -2141,7 +2164,7 @@ LOCAL void php_ion_unserialize_hash(php_ion_unserializer *ser, zval *return_valu } zend_string *key; - php_ion_unserialize_field_name(ser, &key); + php_ion_unserialize_field_name(ser, &key, false); ION_CATCH(); zval zvalue; diff --git a/tests/unserialize/multifield.phpt b/tests/unserialize/multifield.phpt new file mode 100644 index 0000000..6a6e707 --- /dev/null +++ b/tests/unserialize/multifield.phpt @@ -0,0 +1,26 @@ +--TEST-- +ion\unserialize/multifield +--EXTENSIONS-- +ion +--FILE-- +TEST + +DONE +--EXPECT-- +TEST +array(2) { + ["a"]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + ["b"]=> + int(4) +} +DONE diff --git a/tests/unserialize/sid.phpt b/tests/unserialize/sid.phpt new file mode 100644 index 0000000..73c9bc3 --- /dev/null +++ b/tests/unserialize/sid.phpt @@ -0,0 +1,50 @@ +--TEST-- +ion\unserialize/sid +--EXTENSIONS-- +ion +--FILE-- +TEST + +DONE +--EXPECTF-- +TEST +array(2) { + [0]=> + object(ion\Symbol)#%d (3) { + ["value"]=> + string(0) "" + ["sid"]=> + int(33) + ["importLocation"]=> + object(ion\Symbol\ImportLocation)#%d (2) { + ["name"]=> + string(2) "st" + ["location"]=> + int(24) + } + } + [1]=> + array(1) { + ["$99"]=> + object(ion\Symbol)#%d (3) { + ["value"]=> + string(3) "foo" + ["sid"]=> + int(100) + ["importLocation"]=> + NULL + } + } +} +DONE -- 2.30.2