Skip to content

Commit d0460ec

Browse files
authored
[emval] Prevent creating lvalue refs from thin air (#24606)
I'm having trouble reproducing this UB in isolation, but I ran into issues with garbage values in test_i64_val while making other innocent-looking changes. I think it might even explain the really weird bug from #24577 (comment) that magically went away after a rebase despite no related changes being made upstream. Essentially, because I stupidly used `T&&` in a template, and because it's [waves around] C++, it got inferred as `unsigned long long &` instead of the desired `unsigned long long`, so in `.as<T>()` we were quietly returning an `unsigned long long&` reference to a temporary `unsigned long long` value on function stack. Most of the time it somehow still works and, because it's templated, it's not caught by Clang's "non-const lvalue reference to type" diagnostic, but under unrelated changes and optimisations it can break badly.
1 parent 273a3fd commit d0460ec

File tree

2 files changed

+4
-1
lines changed

2 files changed

+4
-1
lines changed

system/include/emscripten/val.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,9 @@ class EMBIND_VISIBILITY_DEFAULT val {
570570

571571
template<internal::EM_INVOKER_KIND Kind, typename Policy, typename Ret, typename... Args>
572572
static Ret internalCall(EM_VAL handle, const char *methodName, Args&&... args) {
573+
static_assert(!std::is_lvalue_reference<Ret>::value,
574+
"Cannot create a lvalue reference out of a JS value.");
575+
573576
using namespace internal;
574577

575578
using RetWire = BindingType<Ret>::WireType;

test/embind/test_i64_val.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ string compare_a_64_js(T value) {
3434
}
3535

3636
template <typename T>
37-
void test_value(T&& value) {
37+
void test_value(T value) {
3838
cout << " testing value " << value << endl;
3939
cout << " setting properties preserves the expected value" << endl;
4040
val::global().set("a", val(value));

0 commit comments

Comments
 (0)