diff --git a/ext/json/ext/fbuffer/fbuffer.h b/ext/json/ext/fbuffer/fbuffer.h index 9660e70d..b84a0735 100644 --- a/ext/json/ext/fbuffer/fbuffer.h +++ b/ext/json/ext/fbuffer/fbuffer.h @@ -131,6 +131,15 @@ static inline void fbuffer_inc_capa(FBuffer *fb, size_t requested) } } +static inline size_t fbuffer_size_mul_or_raise(size_t a, size_t b) +{ + size_t result = a * b; + if (RB_UNLIKELY(a != 0 && (result / a) != b)) { + rb_raise(rb_eArgError, "Buffer overflow, the resulting document is too large to be generated"); + } + return result; +} + static inline void fbuffer_append_reserved(FBuffer *fb, const char *newstr, size_t len) { MEMCPY(fb->ptr + fb->len, newstr, char, len); @@ -175,7 +184,7 @@ static void fbuffer_append_str_repeat(FBuffer *fb, VALUE str, size_t repeat) size_t len; RSTRING_GETMEM(str, ptr, len); - fbuffer_inc_capa(fb, repeat * len); + fbuffer_inc_capa(fb, fbuffer_size_mul_or_raise(repeat, len)); while (repeat) { #if JSON_DEBUG fb->requested = len; diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb index 1cfd19da..87d9cd7f 100755 --- a/test/json/json_generator_test.rb +++ b/test/json/json_generator_test.rb @@ -1081,4 +1081,15 @@ def test_negative_depth_raises end end + def test_large_depth_raises + assert_raise(RangeError, ArgumentError) do + JSON.generate([[1]], + indent: " " * 5, + array_nl: "\n", + depth: 3_689_348_814_741_910_324, + max_nesting: 0 + ) + end + end + end