Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions system/lib/libcxx/new.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,17 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
else
#ifndef _LIBCPP_NO_EXCEPTIONS
throw std::bad_alloc();
#else
#ifdef __EMSCRIPTEN__
// Abort here so that when exceptions are disabled, we do not just
// return 0 when malloc returns 0.
// We could also do this with set_new_handler, but that adds a
// global constructor and a table entry, overhead that we can avoid
// by doing it this way.
abort();
#else
break;
#endif
#endif
}
return p;
Expand Down
9 changes: 9 additions & 0 deletions system/lib/libcxxabi/src/stdlib_new_delete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,17 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
else
#ifndef _LIBCXXABI_NO_EXCEPTIONS
throw std::bad_alloc();
#else
#ifdef __EMSCRIPTEN__
// Abort here so that when exceptions are disabled, we do not just
// return 0 when malloc returns 0.
// We could also do this with set_new_handler, but that adds a
// global constructor and a table entry, overhead that we can avoid
// by doing it this way.
abort();
#else
break;
#endif
#endif
}
return p;
Expand Down
23 changes: 23 additions & 0 deletions tests/core/test_aborting_new.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <emscripten.h>
#include <stdio.h>
#include <vector>

EMSCRIPTEN_KEEPALIVE extern "C" void allocate_too_much() {
std::vector<int> x;
puts("allocating more than TOTAL_MEMORY; this will fail.");
x.resize(20 * 1024 * 1024);
puts("oh no, it didn't fail!");
}

int main() {
EM_ASM({
// Catch the failure here so we can report it.
try {
_allocate_too_much();
out("no abort happened");
} catch (e) {
assert(("" + e).indexOf("abort") >= 0, "expect an abort from new");
out("new aborted as expected");
}
});
}
1 change: 1 addition & 0 deletions tests/core/test_aborting_new.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
new aborted as expected
10 changes: 10 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2169,6 +2169,16 @@ def test_memorygrowth_3_force_fail_reallocBuffer(self):
self.emcc_args += ['-Wno-almost-asm', '-s', 'ALLOW_MEMORY_GROWTH=1', '-s', 'TEST_MEMORY_GROWTH_FAILS=1']
self.do_run_in_out_file_test('tests', 'core', 'test_memorygrowth_3')

@parameterized({
'nogrow': ([],),
'grow': (['-s', 'ALLOW_MEMORY_GROWTH=1', '-s', 'MAXIMUM_MEMORY=18MB'],)
})
def test_aborting_new(self, args):
# test that C++ new properly errors if we fail to malloc when growth is
# enabled, with or without growth
self.emcc_args += ['-Wno-almost-asm'] + args
self.do_run_in_out_file_test('tests', 'core', 'test_aborting_new')

@no_asmjs()
@no_wasm2js('no WebAssembly.Memory()')
@no_asan('ASan alters the memory size')
Expand Down