diff options
| author | nagachika <nagachika@ruby-lang.org> | 2024-03-31 17:37:01 +0900 |
|---|---|---|
| committer | nagachika <nagachika@ruby-lang.org> | 2024-03-31 17:37:01 +0900 |
| commit | 27606daf8efeb0ae6d0590a2c9bb1c5aae07f140 (patch) | |
| tree | be81bc12dd31060be820baa502e66a741fd4b43f | |
| parent | 4f3ed07d5bfd581b630e4afc8b9bb170ce781e7f (diff) | |
merge revision(s) ac0163949a6ee678dfccec9f6e56422b91e5f0a9,01fd262e62076277a41af72ea13f20deb1b462a2: [Backport #20245]
Compile code without Symbol GC always
---
symbol.c | 28 +++++++++++++---------------
1 file changed, 13 insertions(+), 15 deletions(-)
Fix crash when checking symbol encoding
[Bug #20245]
We sometimes pass in a fake string to sym_check_asciionly. This can crash
if sym_check_asciionly raises because it creates a CFP with the fake
string as the receiver which will crash if GC tries to mark the CFP.
For example, the following script crashes:
GC.stress = true
Object.const_defined?("\xC3")
---
symbol.c | 17 ++++++++++-------
test/ruby/test_module.rb | 8 ++++++++
2 files changed, 18 insertions(+), 7 deletions(-)
| -rw-r--r-- | symbol.c | 45 | ||||
| -rw-r--r-- | test/ruby/test_module.rb | 8 | ||||
| -rw-r--r-- | version.h | 2 |
3 files changed, 32 insertions, 23 deletions
@@ -24,7 +24,11 @@ #include "vm_sync.h" #include "builtin.h" -#ifndef USE_SYMBOL_GC +#if defined(USE_SYMBOL_GC) && !(USE_SYMBOL_GC+0) +# undef USE_SYMBOL_GC +# define USE_SYMBOL_GC 0 +#else +# undef USE_SYMBOL_GC # define USE_SYMBOL_GC 1 #endif #ifndef SYMBOL_DEBUG @@ -567,11 +571,14 @@ register_static_symid_str(ID id, VALUE str) } static int -sym_check_asciionly(VALUE str) +sym_check_asciionly(VALUE str, bool fake_str) { if (!rb_enc_asciicompat(rb_enc_get(str))) return FALSE; switch (rb_enc_str_coderange(str)) { case ENC_CODERANGE_BROKEN: + if (fake_str) { + str = rb_enc_str_new(RSTRING_PTR(str), RSTRING_LEN(str), rb_enc_get(str)); + } rb_raise(rb_eEncodingError, "invalid symbol in encoding %s :%+"PRIsVALUE, rb_enc_name(rb_enc_get(str)), str); case ENC_CODERANGE_7BIT: @@ -764,7 +771,7 @@ intern_str(VALUE str, int mutable) id = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN); if (id == (ID)-1) id = ID_JUNK; - if (sym_check_asciionly(str)) { + if (sym_check_asciionly(str, false)) { if (!mutable) str = rb_str_dup(str); rb_enc_associate(str, rb_usascii_encoding()); } @@ -844,12 +851,7 @@ VALUE rb_str_intern(VALUE str) { VALUE sym; -#if USE_SYMBOL_GC - rb_encoding *enc, *ascii; - int type; -#else - ID id; -#endif + GLOBAL_SYMBOLS_ENTER(symbols); { sym = lookup_str_sym_with_lock(symbols, str); @@ -857,11 +859,10 @@ rb_str_intern(VALUE str) if (sym) { // ok } - else { -#if USE_SYMBOL_GC - enc = rb_enc_get(str); - ascii = rb_usascii_encoding(); - if (enc != ascii && sym_check_asciionly(str)) { + else if (USE_SYMBOL_GC) { + rb_encoding *enc = rb_enc_get(str); + rb_encoding *ascii = rb_usascii_encoding(); + if (enc != ascii && sym_check_asciionly(str, false)) { str = rb_str_dup(str); rb_enc_associate(str, ascii); OBJ_FREEZE(str); @@ -872,13 +873,13 @@ rb_str_intern(VALUE str) OBJ_FREEZE(str); } str = rb_fstring(str); - type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN); + int type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN); if (type < 0) type = ID_JUNK; sym = dsymbol_alloc(symbols, rb_cSymbol, str, enc, type); -#else - id = intern_str(str, 0); + } + else { + ID id = intern_str(str, 0); sym = ID2SYM(id); -#endif } } GLOBAL_SYMBOLS_LEAVE(); @@ -1108,7 +1109,7 @@ rb_check_id(volatile VALUE *namep) *namep = name; } - sym_check_asciionly(name); + sym_check_asciionly(name, false); return lookup_str_id(name); } @@ -1167,7 +1168,7 @@ rb_check_symbol(volatile VALUE *namep) *namep = name; } - sym_check_asciionly(name); + sym_check_asciionly(name, false); if ((sym = lookup_str_sym(name)) != 0) { return sym; @@ -1182,7 +1183,7 @@ rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc) struct RString fake_str; const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc); - sym_check_asciionly(name); + sym_check_asciionly(name, true); return lookup_str_id(name); } @@ -1194,7 +1195,7 @@ rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc) struct RString fake_str; const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc); - sym_check_asciionly(name); + sym_check_asciionly(name, true); if ((sym = lookup_str_sym(name)) != 0) { return sym; diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb index dd8cc471d0..6129f0cbbe 100644 --- a/test/ruby/test_module.rb +++ b/test/ruby/test_module.rb @@ -253,6 +253,14 @@ class TestModule < Test::Unit::TestCase assert_operator(Math, :const_defined?, "PI") assert_not_operator(Math, :const_defined?, :IP) assert_not_operator(Math, :const_defined?, "IP") + + # Test invalid symbol name + # [Bug #20245] + EnvUtil.under_gc_stress do + assert_raise(EncodingError) do + Math.const_defined?("\xC3") + end + end end def each_bad_constants(m, &b) @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 3 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 164 +#define RUBY_PATCHLEVEL 165 #include "ruby/version.h" #include "ruby/internal/abi.h" |
