From c18edc5b5d03b9abf355038a17956d69e0552228 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Thu, 21 Dec 2023 16:01:16 -0800 Subject: [PATCH] Avoid underflow of rb_yjit_live_iseq_count This value is only incremented when rb_iseq_translate_threaded_code is called, which doesn't happen for iseqs which result in a syntax error. This is easy to hit by running a debug build with RUBY_FREE_AT_EXIT=1, but any build and options could underflow this value by running enough evals. --- bootstraptest/test_eval.rb | 10 ++++++++++ iseq.c | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/bootstraptest/test_eval.rb b/bootstraptest/test_eval.rb index a9f389c673412b..47e2924846b798 100644 --- a/bootstraptest/test_eval.rb +++ b/bootstraptest/test_eval.rb @@ -227,6 +227,16 @@ def initialize &b }, '[ruby-dev:31372]' end +assert_normal_exit %{ + $stderr = STDOUT + 5000.times do + begin + eval "0 rescue break" + rescue SyntaxError + end + end +} + assert_normal_exit %q{ $stderr = STDOUT class Foo diff --git a/iseq.c b/iseq.c index 40255d3eb0a6d1..27c5bb5d82d907 100644 --- a/iseq.c +++ b/iseq.c @@ -167,8 +167,10 @@ rb_iseq_free(const rb_iseq_t *iseq) rb_rjit_free_iseq(iseq); /* Notify RJIT */ #if USE_YJIT rb_yjit_iseq_free(body->yjit_payload); - RUBY_ASSERT(rb_yjit_live_iseq_count > 0); - rb_yjit_live_iseq_count--; + if (FL_TEST_RAW((VALUE)iseq, ISEQ_TRANSLATED)) { + RUBY_ASSERT(rb_yjit_live_iseq_count > 0); + rb_yjit_live_iseq_count--; + } #endif ruby_xfree((void *)body->iseq_encoded); ruby_xfree((void *)body->insns_info.body);