diff options
author | Kevin Newton <[email protected]> | 2023-11-01 14:28:01 -0400 |
---|---|---|
committer | git <[email protected]> | 2023-11-02 22:14:08 +0000 |
commit | ee7bf4643d2716d44e13a732caf588b1a6275f7a (patch) | |
tree | a943be03a2f1719a8588b3e6a4d9806a4f09489d | |
parent | c6f5c64639152b950d4d1ccbaa199b621099e2a5 (diff) |
[ruby/prism] Handle invalid constants in the constant pool
It's possible for us to parse a constant that is invalid in the
current encoding. To fix this, we wrap the intern function in an
rb_protect to ensure we always put a valid symbol into the AST.
https://github.com/ruby/prism/commit/e78398554d
-rw-r--r-- | prism/prism.c | 7 | ||||
-rw-r--r-- | prism/templates/ext/prism/api_node.c.erb | 12 |
2 files changed, 16 insertions, 3 deletions
diff --git a/prism/prism.c b/prism/prism.c index 42d9712063..de32ccae63 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -8633,13 +8633,16 @@ parser_lex(pm_parser_t *parser) { if (!lex_state_beg_p(parser) && match(parser, '=')) { lex_state_set(parser, PM_LEX_STATE_BEG); LEX(PM_TOKEN_PERCENT_EQUAL); - } - else if( + } else if ( lex_state_beg_p(parser) || (lex_state_p(parser, PM_LEX_STATE_FITEM) && (peek(parser) == 's')) || lex_state_spcarg_p(parser, space_seen) ) { if (!parser->encoding.alnum_char(parser->current.end, parser->end - parser->current.end)) { + if (*parser->current.end >= 0x80) { + pm_parser_err_current(parser, PM_ERR_INVALID_PERCENT); + } + lex_mode_push_string(parser, true, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end)); size_t eol_length = match_eol(parser); diff --git a/prism/templates/ext/prism/api_node.c.erb b/prism/templates/ext/prism/api_node.c.erb index 6da5832185..1ffbf6c9f8 100644 --- a/prism/templates/ext/prism/api_node.c.erb +++ b/prism/templates/ext/prism/api_node.c.erb @@ -83,7 +83,17 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) { for (uint32_t index = 0; index < parser->constant_pool.size; index++) { pm_constant_t *constant = &parser->constant_pool.constants[index]; - constants[index] = rb_intern3((const char *) constant->start, constant->length, encoding); + int state = 0; + + VALUE string = rb_enc_str_new((const char *) constant->start, constant->length, encoding); + ID value = rb_protect(rb_intern_str, string, &state); + + if (state != 0) { + value = rb_intern_const("?"); + rb_set_errinfo(Qnil); + } + + constants[index] = value; } pm_node_stack_node_t *node_stack = NULL; |