From 6e1acbc3427ea738e73cd2674bf0b9d6f066a85d Mon Sep 17 00:00:00 2001 From: Daniel Sloof Date: Sat, 29 Mar 2014 12:56:16 +0100 Subject: [PATCH] fix segfault when cloning objects ObjectData::cloneSet makes the false assertion that an objects dynamic properties can only have string-based keys. When casting an array with numeric keys to an object and then cloning this object will cause HHVM to segfault due to lack of KindOfInt64 support. Closes #2200. Reviewed By: @edwinsmith Differential Revision: D1248203 --- hphp/runtime/base/object-data.cpp | 33 +++++++++++++++++------ hphp/test/slow/clone/numeric-dynprops.php | 5 ++++ hphp/test/slow/clone/numeric-dynprops.php.expectf | 4 +++ 3 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 hphp/test/slow/clone/numeric-dynprops.php create mode 100644 hphp/test/slow/clone/numeric-dynprops.php.expectf diff --git a/hphp/runtime/base/object-data.cpp b/hphp/runtime/base/object-data.cpp index efb6fc6512b..80c9a49adf6 100644 --- a/hphp/runtime/base/object-data.cpp +++ b/hphp/runtime/base/object-data.cpp @@ -1759,16 +1759,33 @@ void ObjectData::cloneSet(ObjectData* clone) { auto props = static_cast(dynProps.get()); TypedValue key; props->nvGetKey(&key, iter); - assert(tvIsString(&key)); - StringData* strKey = key.m_data.pstr; - TypedValue* val = props->nvGet(strKey); - auto const retval = reinterpret_cast( - &cloneProps.lvalAt(String(strKey), AccessFlags::Key) - ); - tvDupFlattenVars(val, retval, cloneProps.get()); + TypedValue* val; + TypedValue* ret; + switch (key.m_type) { + case HPHP::KindOfString: { + StringData* str = key.m_data.pstr; + val = props->nvGet(str); + ret = reinterpret_cast( + &cloneProps.lvalAt(String(str), AccessFlags::Key) + ); + decRefStr(str); + break; + } + case HPHP::KindOfInt64: { + int64_t num = key.m_data.num; + val = props->nvGet(num); + ret = reinterpret_cast( + &cloneProps.lvalAt(num, AccessFlags::Key) + ); + break; + } + default: + always_assert(false); + } + + tvDupFlattenVars(val, ret, cloneProps.get()); iter = dynProps.get()->iter_advance(iter); - decRefStr(strKey); } } } diff --git a/hphp/test/slow/clone/numeric-dynprops.php b/hphp/test/slow/clone/numeric-dynprops.php new file mode 100644 index 00000000000..b70dbf4f2ff --- /dev/null +++ b/hphp/test/slow/clone/numeric-dynprops.php @@ -0,0 +1,5 @@ + '#'); +$b = clone $a; +var_dump($b); diff --git a/hphp/test/slow/clone/numeric-dynprops.php.expectf b/hphp/test/slow/clone/numeric-dynprops.php.expectf new file mode 100644 index 00000000000..40e5247876a --- /dev/null +++ b/hphp/test/slow/clone/numeric-dynprops.php.expectf @@ -0,0 +1,4 @@ +object(stdClass)#%d (1) { + [0]=> + string(1) "#" +} -- 2.11.4.GIT