Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion cont.c
Original file line number Diff line number Diff line change
Expand Up @@ -3651,6 +3651,8 @@ Init_Cont(void)
#endif
SET_MACHINE_STACK_END(&th->ec->machine.stack_end);

rb_eFiberError = rb_define_class("FiberError", rb_eStandardError);

size_t minimum_count = shared_fiber_pool_minimum_count();
size_t maximum_count = shared_fiber_pool_maximum_count();
fiber_pool_initialize(&shared_fiber_pool, stack_size, minimum_count, maximum_count, vm_stack_size);
Expand All @@ -3675,7 +3677,6 @@ Init_Cont(void)

rb_cFiber = rb_define_class("Fiber", rb_cObject);
rb_define_alloc_func(rb_cFiber, fiber_alloc);
rb_eFiberError = rb_define_class("FiberError", rb_eStandardError);
rb_define_singleton_method(rb_cFiber, "yield", rb_fiber_s_yield, -1);
rb_define_singleton_method(rb_cFiber, "current", rb_fiber_s_current, 0);
rb_define_singleton_method(rb_cFiber, "blocking", rb_fiber_blocking, 0);
Expand Down
11 changes: 10 additions & 1 deletion ext/json/fbuffer/fbuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
43 changes: 31 additions & 12 deletions parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -1659,7 +1659,22 @@ static NODE *add_block_exit(struct parser_params *p, NODE *node);
static rb_node_exits_t *init_block_exit(struct parser_params *p);
static rb_node_exits_t *allow_block_exit(struct parser_params *p);
static void restore_block_exit(struct parser_params *p, rb_node_exits_t *exits);
static void clear_block_exit(struct parser_params *p, bool error);
static void clear_block_exit(struct parser_params *p, unsigned int error_mask);

static unsigned int
exits_mask(enum node_type t)
{
switch (t) {
case NODE_BREAK:
case NODE_NEXT:
case NODE_REDO:
return 1u << (t - NODE_BREAK);
default:
UNREACHABLE_RETURN(0);
}
}

#define EXITS_MASK_ALL (exits_mask(NODE_BREAK)|exits_mask(NODE_NEXT)|exits_mask(NODE_REDO))

static void
next_rescue_context(struct lex_context *next, const struct lex_context *outer, enum rescue_context def)
Expand All @@ -1677,7 +1692,7 @@ restore_defun(struct parser_params *p, rb_node_def_temp_t *temp)
p->ctxt.in_rescue = ctxt.in_rescue;
p->max_numparam = temp->save.max_numparam;
numparam_pop(p, temp->save.numparam_save);
clear_block_exit(p, true);
clear_block_exit(p, EXITS_MASK_ALL);
}

static void
Expand Down Expand Up @@ -1834,20 +1849,23 @@ restore_block_exit(struct parser_params *p, rb_node_exits_t *exits)
}

static void
clear_block_exit(struct parser_params *p, bool error)
clear_block_exit(struct parser_params *p, unsigned int error_mask)
{
rb_node_exits_t *exits = p->exits;
if (!exits) return;
if (error) {
if (error_mask) {
for (NODE *e = RNODE(exits); (e = RNODE_EXITS(e)->nd_chain) != 0; ) {
switch (nd_type(e)) {
case NODE_BREAK:
if (!(error_mask & exits_mask(NODE_BREAK))) break;
yyerror1(&e->nd_loc, "Invalid break");
break;
case NODE_NEXT:
if (!(error_mask & exits_mask(NODE_NEXT))) break;
yyerror1(&e->nd_loc, "Invalid next");
break;
case NODE_REDO:
if (!(error_mask & exits_mask(NODE_REDO))) break;
yyerror1(&e->nd_loc, "Invalid redo");
break;
default:
Expand Down Expand Up @@ -3212,7 +3230,7 @@ top_stmts : none

top_stmt : stmt
{
clear_block_exit(p, true);
clear_block_exit(p, EXITS_MASK_ALL);
$$ = $1;
}
| keyword_BEGIN begin_block
Expand Down Expand Up @@ -3296,6 +3314,9 @@ allow_exits : {$$ = allow_block_exit(p);};

k_END : keyword_END lex_ctxt
{
if (p->ctxt.in_def) {
rb_warn0("END in method; use at_exit");
}
$$ = $2;
p->ctxt.in_rescue = before_rescue;
/*% ripper: $:2 %*/
Expand Down Expand Up @@ -3349,7 +3370,7 @@ stmt : keyword_alias[kw] fitem[new] {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fit
}
| stmt[body] modifier_while[mod] expr_value[cond_expr]
{
clear_block_exit(p, false);
clear_block_exit(p, 0);
if ($body && nd_type_p($body, NODE_BEGIN)) {
$$ = NEW_WHILE(cond(p, $cond_expr, &@cond_expr), RNODE_BEGIN($body)->nd_body, 0, &@$, &@mod, &NULL_LOC);
}
Expand All @@ -3360,7 +3381,7 @@ stmt : keyword_alias[kw] fitem[new] {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fit
}
| stmt[body] modifier_until[mod] expr_value[cond_expr]
{
clear_block_exit(p, false);
clear_block_exit(p, 0);
if ($body && nd_type_p($body, NODE_BEGIN)) {
$$ = NEW_UNTIL(cond(p, $cond_expr, &@cond_expr), RNODE_BEGIN($body)->nd_body, 0, &@$, &@mod, &NULL_LOC);
}
Expand All @@ -3378,12 +3399,10 @@ stmt : keyword_alias[kw] fitem[new] {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fit
$$ = NEW_RESCUE(remove_begin($body), resq, 0, &@$);
/*% ripper: rescue_mod!($:body, $:resbody) %*/
}
| k_END[k_end] allow_exits[allow] '{'[lbrace] compstmt(stmts)[body] '}'[rbrace]
| k_END[k_end] block_open[lbrace] compstmt(stmts)[body] '}'[rbrace]
{
if (p->ctxt.in_def) {
rb_warn0("END in method; use at_exit");
}
restore_block_exit(p, $allow);
clear_block_exit(p, exits_mask(NODE_BREAK) | exits_mask(NODE_REDO));
restore_block_exit(p, $block_open);
p->ctxt = $k_end;
{
NODE *scope = NEW_SCOPE2(0 /* tbl */, 0 /* args */, $body /* body */, NULL /* parent */, &@$);
Expand Down
11 changes: 11 additions & 0 deletions test/json/json_generator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 5 additions & 1 deletion test/ruby/test_ast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,11 @@ def test_invalid_exit
assert_invalid_parse(msg, "#{code}")
assert_invalid_parse(msg, "def m; #{code}; end")
assert_invalid_parse(msg, "begin; #{code}; end")
assert_parse("END {#{code}}")
if code.start_with?("next")
assert_parse("END {#{code}}")
else
assert_invalid_parse(msg, "END {#{code}}")
end

assert_parse("!defined?(#{code})")
assert_parse("def m; defined?(#{code}); end")
Expand Down
3 changes: 2 additions & 1 deletion test/ruby/test_beginendblock.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ def test_endblockwarn
assert_in_out_err([], "#{<<~"begin;"}#{<<~'end;'}", [], ['-:2: warning: END in method; use at_exit'])
begin;
def end1
END {}
END {
}
end
end;
end
Expand Down