Skip to content

Commit 47401da

Browse files
authored
Merge pull request #737 from wasmx/memory-grow-exceptions
Improve exception handling in memory.grow
2 parents 25205ab + 3864569 commit 47401da

File tree

1 file changed

+50
-17
lines changed

1 file changed

+50
-17
lines changed

lib/fizzy/execute.cpp

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,54 @@ inline bool store_into_memory(
109109
return true;
110110
}
111111

112+
/// Checks that exception is one of the types expected to be thrown from bytes::resize().
113+
/// We catch ... in memory.grow implementation for the sake of smaller binary code and assert it's
114+
/// one of expected exceptions.
115+
[[maybe_unused]] bool is_resize_exception(std::exception_ptr exception) noexcept
116+
{
117+
try
118+
{
119+
std::rethrow_exception(exception);
120+
}
121+
catch (const std::bad_alloc&)
122+
{
123+
return true;
124+
}
125+
catch (const std::length_error&)
126+
{
127+
return true;
128+
}
129+
catch (...)
130+
{
131+
return false;
132+
}
133+
}
134+
135+
/// Increases the size of memory by @a delta_pages.
136+
/// @return Number of memory pages before expansion if successful, otherwise 2^32-1 in case
137+
/// requested resize goes above @a memory_pages_limit or if allocation failed.
138+
inline uint32_t grow_memory(
139+
bytes& memory, uint32_t delta_pages, uint32_t memory_pages_limit) noexcept
140+
{
141+
const auto cur_pages = memory.size() / PageSize;
142+
assert(cur_pages <= size_t(std::numeric_limits<int32_t>::max()));
143+
const auto new_pages = cur_pages + delta_pages;
144+
assert(new_pages >= cur_pages);
145+
if (new_pages > memory_pages_limit)
146+
return static_cast<uint32_t>(-1);
147+
148+
try
149+
{
150+
memory.resize(new_pages * PageSize);
151+
return static_cast<uint32_t>(cur_pages);
152+
}
153+
catch (...)
154+
{
155+
assert(is_resize_exception(std::current_exception()));
156+
return static_cast<uint32_t>(-1);
157+
}
158+
}
159+
112160
/// Converts the top stack item by truncating a float value to an integer value.
113161
template <typename SrcT, typename DstT>
114162
inline bool trunc(OperandStack& stack) noexcept
@@ -828,23 +876,8 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args,
828876
}
829877
case Instr::memory_grow:
830878
{
831-
const auto delta = stack.pop().as<uint32_t>();
832-
const auto cur_pages = memory->size() / PageSize;
833-
assert(cur_pages <= size_t(std::numeric_limits<int32_t>::max()));
834-
const auto new_pages = cur_pages + delta;
835-
assert(new_pages >= cur_pages);
836-
uint32_t ret = static_cast<uint32_t>(cur_pages);
837-
try
838-
{
839-
if (new_pages > instance.memory_pages_limit)
840-
throw std::bad_alloc();
841-
memory->resize(new_pages * PageSize);
842-
}
843-
catch (std::bad_alloc const&)
844-
{
845-
ret = static_cast<uint32_t>(-1);
846-
}
847-
stack.push(ret);
879+
stack.top() =
880+
grow_memory(*memory, stack.top().as<uint32_t>(), instance.memory_pages_limit);
848881
break;
849882
}
850883
case Instr::i32_const:

0 commit comments

Comments
 (0)