Skip to content

Commit 5d688ec

Browse files
authored
[embind] Only allow class types for unique_ptr bindings. (#21637)
As pointed out by #21625, when using unique_ptr's with primitive types the raw pointer was being passed between wasm and JS, but it was using the underlying type (e.g. char, int, etc) to convert the value. This means the pointer was truncated to a char at the boundary. Embind doesn't allow pointers or references to primitive types so it doesn't make sense to allow a unique_ptr for these types either.
1 parent 47e23e5 commit 5d688ec

File tree

3 files changed

+24
-9
lines changed

3 files changed

+24
-9
lines changed

system/include/emscripten/wire.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ struct TypeID {
106106

107107
template<typename T>
108108
struct TypeID<std::unique_ptr<T>> {
109+
static_assert(std::is_class<T>::value, "The type for a std::unique_ptr binding must be a class.");
109110
static constexpr TYPEID get() {
110111
return TypeID<T>::get();
111112
}

test/embind/embind_test.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,30 +1043,42 @@ void emval_test_call_function(val v, int i, float f, TupleVector tv, StructVecto
10431043
v(i, f, tv, sv);
10441044
}
10451045

1046+
struct CharWrapper {
1047+
CharWrapper(char v) {
1048+
value = v;
1049+
};
1050+
1051+
char getValue() {
1052+
return value;
1053+
}
1054+
1055+
char value;
1056+
};
1057+
10461058
class UniquePtrToConstructor {
10471059
public:
1048-
UniquePtrToConstructor(std::unique_ptr<int> p)
1049-
: value(*p)
1060+
UniquePtrToConstructor(std::unique_ptr<CharWrapper> p)
1061+
: value((*p).getValue())
10501062
{}
10511063

1052-
int getValue() const {
1064+
char getValue() const {
10531065
return value;
10541066
}
10551067

10561068
private:
1057-
int value;
1069+
char value;
10581070
};
10591071

1060-
std::unique_ptr<int> embind_test_return_unique_ptr(int v) {
1061-
return std::unique_ptr<int>(new int(v));
1072+
std::unique_ptr<CharWrapper> embind_test_return_unique_ptr(char v) {
1073+
return std::unique_ptr<CharWrapper>(new CharWrapper(v));
10621074
}
10631075

1064-
UniquePtrToConstructor* embind_test_construct_class_with_unique_ptr(int v) {
1076+
UniquePtrToConstructor* embind_test_construct_class_with_unique_ptr(char v) {
10651077
return new UniquePtrToConstructor(embind_test_return_unique_ptr(v));
10661078
}
10671079

1068-
int embind_test_accept_unique_ptr(std::unique_ptr<int> p) {
1069-
return *p.get();
1080+
char embind_test_accept_unique_ptr(std::unique_ptr<CharWrapper> p) {
1081+
return (*p.get()).getValue();
10701082
}
10711083

10721084
std::unique_ptr<ValHolder> emval_test_return_unique_ptr() {
@@ -2251,6 +2263,7 @@ EMSCRIPTEN_BINDINGS(tests) {
22512263
class_<UniquePtrToConstructor>("UniquePtrToConstructor")
22522264
.function("getValue", &UniquePtrToConstructor::getValue)
22532265
;
2266+
class_<CharWrapper>("CharWrapper");
22542267

22552268
function("embind_test_construct_class_with_unique_ptr", embind_test_construct_class_with_unique_ptr, allow_raw_pointer<ret_val>());
22562269
function("embind_test_return_unique_ptr", embind_test_return_unique_ptr);

test/test_other.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3113,6 +3113,7 @@ def test_embind_closure_no_dynamic_execution(self):
31133113
'no_dynamic': ['-sDYNAMIC_EXECUTION=0'],
31143114
'aot_js': ['-sDYNAMIC_EXECUTION=0', '-sEMBIND_AOT', '-DSKIP_UNBOUND_TYPES'],
31153115
'wasm64': ['-sMEMORY64', '-Wno-experimental'],
3116+
'2gb': ['-sINITIAL_MEMORY=2200mb', '-sGLOBAL_BASE=2gb'],
31163117
})
31173118
@parameterized({
31183119
# With no arguments we are effectively testing c++17 since it is the default.

0 commit comments

Comments
 (0)