1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

merge revision(s) 7e8a9af9db: [Backport #17732]

rb_enc_interned_str: handle autoloaded encodings

	If called with an autoloaded encoding that was not yet
	initialized, `rb_enc_interned_str` would crash with
	a NULL pointer exception.

	See: https://github.com/ruby/ruby/pull/4119#issuecomment-800189841
	---
	 encoding.c                        | 28 ++++++++++++----------------
	 ext/-test-/string/depend          |  3 +++
	 ext/-test-/string/fstring.c       | 15 +++++++++++++++
	 internal/encoding.h               |  3 +++
	 string.c                          |  4 ++++
	 test/-ext-/string/test_fstring.rb | 16 ++++++++++++++++
	 6 files changed, 53 insertions(+), 16 deletions(-)
This commit is contained in:
NARUSE, Yui 2021-04-02 16:06:31 +09:00
parent 855401da49
commit 4e2738f477
7 changed files with 54 additions and 17 deletions

View file

@ -101,8 +101,6 @@ static rb_encoding *global_enc_ascii,
#define ENCODING_NAMELEN_MAX 63
#define valid_encoding_name_p(name) ((name) && strlen(name) <= ENCODING_NAMELEN_MAX)
#define enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc))
static const rb_data_type_t encoding_data_type = {
"encoding",
{0, 0, 0,},
@ -207,16 +205,14 @@ rb_enc_dummy_p(rb_encoding *enc)
return ENC_DUMMY_P(enc) != 0;
}
static int enc_autoload(rb_encoding *);
static int
check_encoding(rb_encoding *enc)
{
int index = rb_enc_to_index(enc);
if (rb_enc_from_index(index) != enc)
return -1;
if (enc_autoload_p(enc)) {
index = enc_autoload(enc);
if (rb_enc_autoload_p(enc)) {
index = rb_enc_autoload(enc);
}
return index;
}
@ -260,7 +256,7 @@ must_encindex(int index)
rb_raise(rb_eEncodingError, "wrong encoding index %d for %s (expected %d)",
index, rb_enc_name(enc), ENC_TO_ENCINDEX(enc));
}
if (enc_autoload_p(enc) && enc_autoload(enc) == -1) {
if (rb_enc_autoload_p(enc) && rb_enc_autoload(enc) == -1) {
rb_loaderror("failed to load encoding (%s)",
rb_enc_name(enc));
}
@ -444,7 +440,7 @@ rb_enc_register(const char *name, rb_encoding *encoding)
if (STRCASECMP(name, rb_enc_name(oldenc))) {
index = enc_register(enc_table, name, encoding);
}
else if (enc_autoload_p(oldenc) || !ENC_DUMMY_P(oldenc)) {
else if (rb_enc_autoload_p(oldenc) || !ENC_DUMMY_P(oldenc)) {
enc_register_at(enc_table, index, name, encoding);
}
else {
@ -834,7 +830,7 @@ load_encoding(const char *name)
else if ((idx = enc_registered(enc_table, name)) < 0) {
idx = -1;
}
else if (enc_autoload_p(enc_table->list[idx].enc)) {
else if (rb_enc_autoload_p(enc_table->list[idx].enc)) {
idx = -1;
}
}
@ -853,8 +849,8 @@ enc_autoload_body(struct enc_table *enc_table, rb_encoding *enc)
do {
if (i >= enc_table->count) return -1;
} while (enc_table->list[i].enc != base && (++i, 1));
if (enc_autoload_p(base)) {
if (enc_autoload(base) < 0) return -1;
if (rb_enc_autoload_p(base)) {
if (rb_enc_autoload(base) < 0) return -1;
}
i = enc->ruby_encoding_index;
enc_register_at(enc_table, i & ENC_INDEX_MASK, rb_enc_name(enc), base);
@ -867,8 +863,8 @@ enc_autoload_body(struct enc_table *enc_table, rb_encoding *enc)
}
}
static int
enc_autoload(rb_encoding *enc)
int
rb_enc_autoload(rb_encoding *enc)
{
int i;
GLOBAL_ENC_TABLE_EVAL(enc_table, i = enc_autoload_body(enc_table, enc));
@ -895,8 +891,8 @@ rb_enc_find_index(const char *name)
rb_raise(rb_eArgError, "encoding %s is not registered", name);
}
}
else if (enc_autoload_p(enc)) {
if (enc_autoload(enc) < 0) {
else if (rb_enc_autoload_p(enc)) {
if (rb_enc_autoload(enc) < 0) {
rb_warn("failed to load encoding (%s); use ASCII-8BIT instead",
name);
return 0;
@ -1340,7 +1336,7 @@ enc_inspect(VALUE self)
"#<%"PRIsVALUE":%s%s%s>", rb_obj_class(self),
rb_enc_name(enc),
(ENC_DUMMY_P(enc) ? " (dummy)" : ""),
enc_autoload_p(enc) ? " (autoload)" : "");
rb_enc_autoload_p(enc) ? " (autoload)" : "");
}
/*

View file

@ -1000,6 +1000,7 @@ fstring.o: $(hdrdir)/ruby/backward/2/long_long.h
fstring.o: $(hdrdir)/ruby/backward/2/stdalign.h
fstring.o: $(hdrdir)/ruby/backward/2/stdarg.h
fstring.o: $(hdrdir)/ruby/defines.h
fstring.o: $(hdrdir)/ruby/encoding.h
fstring.o: $(hdrdir)/ruby/intern.h
fstring.o: $(hdrdir)/ruby/internal/anyargs.h
fstring.o: $(hdrdir)/ruby/internal/arithmetic.h
@ -1142,6 +1143,8 @@ fstring.o: $(hdrdir)/ruby/internal/variable.h
fstring.o: $(hdrdir)/ruby/internal/warning_push.h
fstring.o: $(hdrdir)/ruby/internal/xmalloc.h
fstring.o: $(hdrdir)/ruby/missing.h
fstring.o: $(hdrdir)/ruby/onigmo.h
fstring.o: $(hdrdir)/ruby/oniguruma.h
fstring.o: $(hdrdir)/ruby/ruby.h
fstring.o: $(hdrdir)/ruby/st.h
fstring.o: $(hdrdir)/ruby/subst.h

View file

@ -1,4 +1,5 @@
#include "ruby.h"
#include "ruby/encoding.h"
VALUE rb_fstring(VALUE str);
@ -8,8 +9,22 @@ bug_s_fstring(VALUE self, VALUE str)
return rb_fstring(str);
}
VALUE
bug_s_rb_enc_interned_str(VALUE self, VALUE encoding)
{
return rb_enc_interned_str("foo", 3, RDATA(encoding)->data);
}
VALUE
bug_s_rb_enc_str_new(VALUE self, VALUE encoding)
{
return rb_enc_str_new("foo", 3, RDATA(encoding)->data);
}
void
Init_string_fstring(VALUE klass)
{
rb_define_singleton_method(klass, "fstring", bug_s_fstring, 1);
rb_define_singleton_method(klass, "rb_enc_interned_str", bug_s_rb_enc_interned_str, 1);
rb_define_singleton_method(klass, "rb_enc_str_new", bug_s_rb_enc_str_new, 1);
}

View file

@ -12,12 +12,15 @@
#include "ruby/ruby.h" /* for ID */
#include "ruby/encoding.h" /* for rb_encoding */
#define rb_enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc))
/* encoding.c */
ID rb_id_encoding(void);
rb_encoding *rb_enc_get_from_index(int index);
rb_encoding *rb_enc_check_str(VALUE str1, VALUE str2);
int rb_encdb_replicate(const char *alias, const char *orig);
int rb_encdb_alias(const char *alias, const char *orig);
int rb_enc_autoload(rb_encoding *enc);
int rb_encdb_dummy(const char *name);
void rb_encdb_declare(const char *name);
void rb_enc_set_base(const char *name, const char *orig);

View file

@ -11505,6 +11505,10 @@ rb_interned_str_cstr(const char *ptr)
VALUE
rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc)
{
if (UNLIKELY(rb_enc_autoload_p(enc))) {
rb_enc_autoload(enc);
}
struct RString fake_str;
return register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc), TRUE);
}

View file

@ -12,6 +12,22 @@ class Test_String_Fstring < Test::Unit::TestCase
yield fstr
end
def test_rb_enc_interned_str_autoloaded_encoding
assert_separately([], <<~RUBY)
require '-test-/string'
assert_include(Encoding::Windows_31J.inspect, 'autoload')
Bug::String.rb_enc_interned_str(Encoding::Windows_31J)
RUBY
end
def test_rb_enc_str_new_autoloaded_encoding
assert_separately([], <<~RUBY)
require '-test-/string'
assert_include(Encoding::Windows_31J.inspect, 'autoload')
Bug::String.rb_enc_str_new(Encoding::Windows_31J)
RUBY
end
def test_instance_variable
str = __method__.to_s * 3
str.instance_variable_set(:@test, 42)

View file

@ -12,7 +12,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 0
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
#define RUBY_PATCHLEVEL 60
#define RUBY_PATCHLEVEL 61
#define RUBY_RELEASE_YEAR 2021
#define RUBY_RELEASE_MONTH 4