Skip to content

Commit de993aa

Browse files
thesmartshadowbyroot
authored andcommitted
Reject negative depth; add overflow guards to prevent hang/crash
1 parent 6ccc102 commit de993aa

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

ext/json/ext/generator/generator.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,6 +1575,17 @@ static long long_config(VALUE num)
15751575
return RTEST(num) ? FIX2LONG(num) : 0;
15761576
}
15771577

1578+
// depth must never be negative; reject early with a clear error.
1579+
static long depth_config(VALUE num)
1580+
{
1581+
if (!RTEST(num)) return 0;
1582+
long d = NUM2LONG(num);
1583+
if (RB_UNLIKELY(d < 0)) {
1584+
rb_raise(rb_eArgError, "depth must be >= 0 (got %ld)", d);
1585+
}
1586+
return d;
1587+
}
1588+
15781589
/*
15791590
* call-seq: max_nesting=(depth)
15801591
*
@@ -1731,7 +1742,7 @@ static VALUE cState_depth_set(VALUE self, VALUE depth)
17311742
{
17321743
rb_check_frozen(self);
17331744
GET_STATE(self);
1734-
state->depth = long_config(depth);
1745+
state->depth = depth_config(depth);
17351746
return Qnil;
17361747
}
17371748

@@ -1796,7 +1807,7 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
17961807
else if (key == sym_max_nesting) { state->max_nesting = long_config(val); }
17971808
else if (key == sym_allow_nan) { state->allow_nan = RTEST(val); }
17981809
else if (key == sym_ascii_only) { state->ascii_only = RTEST(val); }
1799-
else if (key == sym_depth) { state->depth = long_config(val); }
1810+
else if (key == sym_depth) { state->depth = depth_config(val); }
18001811
else if (key == sym_buffer_initial_length) { buffer_initial_length_set(state, val); }
18011812
else if (key == sym_script_safe) { state->script_safe = RTEST(val); }
18021813
else if (key == sym_escape_slash) { state->script_safe = RTEST(val); }

test/json/json_generator_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,4 +1045,14 @@ def test_nesting_recovery
10451045
assert_equal 0, state.depth
10461046
assert_equal '{"a":1}', state.generate({ a: 1 })
10471047
end
1048+
1049+
def test_negative_depth_raises
1050+
assert_raise(ArgumentError) do
1051+
JSON.generate({"a" => 1}, depth: -1)
1052+
end
1053+
assert_raise(ArgumentError) do
1054+
JSON.state.new(depth: -1)
1055+
end
1056+
end
1057+
10481058
end

0 commit comments

Comments
 (0)