From 88107fa030786946b7f9a4d2db695bddf987a5a9 Mon Sep 17 00:00:00 2001 From: Kevin Viratyosin Date: Wed, 8 May 2019 15:00:04 -0700 Subject: [PATCH] Avoid `Lval on missing array element` logs from `IniSettingMap::set` Summary: The following command was resulting in stackless notices `Hack Array Compat: Lval on missing array element`: ``` /usr/local/hphpi/bin/hhvm -vEval.HackArrCompatNotices=1 -vEval.HackArrCompatCheckFalseyPromote=1 -m debug ``` I used `gdb` to trace this to two `lvalAt` calls via `IniSettingMap::set`. I'm not sure if initializing the value at the missing key to null (`empty_array()`) is the best thing to but, it looks like the merging will just overwrite it. Reviewed By: mofarrell Differential Revision: D15202922 fbshipit-source-id: 354cd3e36f53a05aee33dc49208897413ac0dc73 --- hphp/runtime/base/ini-setting.cpp | 12 ++++++++++-- hphp/test/slow/debugger/no-lval-on-missing.php | 1 + hphp/test/slow/debugger/no-lval-on-missing.php.expectf | 2 ++ hphp/test/slow/debugger/no-lval-on-missing.php.opts | 1 + 4 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 hphp/test/slow/debugger/no-lval-on-missing.php create mode 100644 hphp/test/slow/debugger/no-lval-on-missing.php.expectf create mode 100644 hphp/test/slow/debugger/no-lval-on-missing.php.opts diff --git a/hphp/runtime/base/ini-setting.cpp b/hphp/runtime/base/ini-setting.cpp index 750e1d45953..9e40c356b1c 100644 --- a/hphp/runtime/base/ini-setting.cpp +++ b/hphp/runtime/base/ini-setting.cpp @@ -554,7 +554,11 @@ void mergeSettings(tv_lval curval, TypedValue v) { if (isArrayLikeType(cell.m_type) && isArrayLikeType(cur_inner.type())) { for (auto i = ArrayIter(cell.m_data.parr); !i.end(); i.next()) { - mergeSettings(asArrRef(cur_inner).lvalAt(i.first()), i.secondVal()); + auto& cur_inner_ref = asArrRef(cur_inner); + if (!cur_inner_ref.exists(i.first())) { + cur_inner_ref.set(i.first(), empty_array()); + } + mergeSettings(cur_inner_ref.lvalAt(i.first()), i.secondVal()); } } else { tvSet(tvToInitCell(v), curval); @@ -564,7 +568,11 @@ void mergeSettings(tv_lval curval, TypedValue v) { void IniSettingMap::set(const String& key, const Variant& v) { assertx(this->isArray()); - auto const curval = m_map.toArrRef().lvalAt(key); + auto& mapref = m_map.toArrRef(); + if (!mapref.exists(key)) { + mapref.set(key, empty_array()); + } + auto const curval = mapref.lvalAt(key); mergeSettings(curval, *v.asTypedValue()); } diff --git a/hphp/test/slow/debugger/no-lval-on-missing.php b/hphp/test/slow/debugger/no-lval-on-missing.php new file mode 100644 index 00000000000..d2b3750ee00 --- /dev/null +++ b/hphp/test/slow/debugger/no-lval-on-missing.php @@ -0,0 +1 @@ +