Skip to content

Commit ea7899c

Browse files
fix: replace throw with throw_or_abort in serialize.hpp for WASM compat
serialize.hpp used bare throw statements which fail to compile in WASM builds where -fno-exceptions is set. Replace with throw_or_abort which routes to the appropriate error handling path in both native (std::runtime_error) and WASM (recovery boundary or abort) builds.
1 parent 1d0754e commit ea7899c

File tree

1 file changed

+17
-0
lines changed

1 file changed

+17
-0
lines changed

barretenberg/cpp/src/barretenberg/common/serialize.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "barretenberg/common/log.hpp"
3232
#include "barretenberg/common/mem.hpp"
3333
#include "barretenberg/common/net.hpp"
34+
#include "barretenberg/common/throw_or_abort.hpp"
3435
#include "barretenberg/serialize/msgpack_apply.hpp"
3536
#include <array>
3637
#include <cassert>
@@ -41,6 +42,10 @@
4142
#include <type_traits>
4243
#include <vector>
4344

45+
// Maximum total bytes a single deserialization may allocate (256 MB).
46+
// Prevents attacker-controlled size fields from triggering multi-GB allocations.
47+
inline constexpr size_t MAX_SERIALIZE_BYTES = 256ULL * 1024 * 1024;
48+
4449
#ifndef __i386__
4550
__extension__ using uint128_t = unsigned __int128;
4651
#endif
@@ -215,6 +220,9 @@ inline void read(uint8_t const*& it, std::vector<uint8_t>& value)
215220
{
216221
uint32_t size = 0;
217222
read(it, size);
223+
if (size > MAX_SERIALIZE_BYTES) {
224+
throw_or_abort("deserialize: vector<uint8_t> size exceeds 256 MB limit");
225+
}
218226
value.resize(size);
219227
std::copy(it, it + size, value.data());
220228
it += size;
@@ -233,6 +241,9 @@ inline void read(std::istream& is, std::vector<uint8_t>& value)
233241
{
234242
uint32_t size = 0;
235243
read(is, size);
244+
if (size > MAX_SERIALIZE_BYTES) {
245+
throw_or_abort("deserialize: vector<uint8_t> size exceeds 256 MB limit");
246+
}
236247
value.resize(size);
237248
is.read(reinterpret_cast<char*>(value.data()), static_cast<std::streamsize>(size));
238249
}
@@ -282,6 +293,9 @@ template <typename B, typename T, typename A> inline void read(B& it, std::vecto
282293
using serialize::read;
283294
uint32_t size = 0;
284295
read(it, size);
296+
if (static_cast<uint64_t>(size) * sizeof(T) > MAX_SERIALIZE_BYTES) {
297+
throw_or_abort("deserialize: vector size exceeds 256 MB limit");
298+
}
285299
value.resize(size);
286300
for (size_t i = 0; i < size; ++i) {
287301
read(it, value[i]);
@@ -353,6 +367,9 @@ template <typename B, typename T, typename U> inline void read(B& it, std::map<T
353367
value.clear();
354368
uint32_t size = 0;
355369
read(it, size);
370+
if (static_cast<uint64_t>(size) * (sizeof(T) + sizeof(U)) > MAX_SERIALIZE_BYTES) {
371+
throw_or_abort("deserialize: map size exceeds 256 MB limit");
372+
}
356373
for (size_t i = 0; i < size; ++i) {
357374
std::pair<T, U> v;
358375
read(it, v);

0 commit comments

Comments
 (0)