From cfa0035962f7c373ca612be5bee749803368fd5b Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 7 Jul 2011 06:44:46 +0000 Subject: [PATCH] * encoding.c (rb_enc_set_index, rb_enc_associate_index): should check if frozen. * parse.y (rb_intern3), ruby.c (process_options, ruby_script): defer freezing after associating encodings. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32435 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 8 ++++++++ encoding.c | 15 +++++++++++---- ext/-test-/string/enc_associate.c | 13 +++++++++++++ parse.y | 3 ++- ruby.c | 5 +++-- test/-ext-/string/test_enc_associate.rb | 12 ++++++++++++ 6 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 ext/-test-/string/enc_associate.c create mode 100644 test/-ext-/string/test_enc_associate.rb diff --git a/ChangeLog b/ChangeLog index 7b2a5298ba..4cb879ee30 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Thu Jul 7 15:44:42 2011 Nobuyoshi Nakada + + * encoding.c (rb_enc_set_index, rb_enc_associate_index): should + check if frozen. + + * parse.y (rb_intern3), ruby.c (process_options, ruby_script): + defer freezing after associating encodings. + Thu Jul 7 15:16:51 2011 NARUSE, Yui * numeric.c (rb_num2ull): use own switch sentense. diff --git a/encoding.c b/encoding.c index 95b2767911..0b6bf96bc5 100644 --- a/encoding.c +++ b/encoding.c @@ -685,8 +685,8 @@ rb_enc_get_index(VALUE obj) return i; } -void -rb_enc_set_index(VALUE obj, int idx) +static void +enc_set_index(VALUE obj, int idx) { if (idx < ENCODING_INLINE_MAX) { ENCODING_SET_INLINED(obj, idx); @@ -694,13 +694,20 @@ rb_enc_set_index(VALUE obj, int idx) } ENCODING_SET_INLINED(obj, ENCODING_INLINE_MAX); rb_ivar_set(obj, rb_id_encoding(), INT2NUM(idx)); - return; +} + +void +rb_enc_set_index(VALUE obj, int idx) +{ + rb_check_frozen(obj); + enc_set_index(obj, idx); } VALUE rb_enc_associate_index(VALUE obj, int idx) { /* enc_check_capable(obj);*/ + rb_check_frozen(obj); if (rb_enc_get_index(obj) == idx) return obj; if (SPECIAL_CONST_P(obj)) { @@ -710,7 +717,7 @@ rb_enc_associate_index(VALUE obj, int idx) !rb_enc_asciicompat(rb_enc_from_index(idx))) { ENC_CODERANGE_CLEAR(obj); } - rb_enc_set_index(obj, idx); + enc_set_index(obj, idx); return obj; } diff --git a/ext/-test-/string/enc_associate.c b/ext/-test-/string/enc_associate.c new file mode 100644 index 0000000000..2ecc9c0227 --- /dev/null +++ b/ext/-test-/string/enc_associate.c @@ -0,0 +1,13 @@ +#include "ruby.h" + +VALUE +bug_str_enc_associate(VALUE str, VALUE enc) +{ + return rb_enc_associate(str, rb_to_encoding(enc)); +} + +void +Init_enc_associate(VALUE klass) +{ + rb_define_method(klass, "associate_encoding!", bug_str_enc_associate, 1); +} diff --git a/parse.y b/parse.y index 015ad51531..9769bb9887 100644 --- a/parse.y +++ b/parse.y @@ -9723,13 +9723,14 @@ rb_intern3(const char *name, long len, rb_encoding *enc) int mb; st_data_t data; struct RString fake_str; - fake_str.basic.flags = T_STRING|RSTRING_NOEMBED|FL_FREEZE; + fake_str.basic.flags = T_STRING|RSTRING_NOEMBED; fake_str.basic.klass = rb_cString; fake_str.as.heap.len = len; fake_str.as.heap.ptr = (char *)name; fake_str.as.heap.aux.capa = len; str = (VALUE)&fake_str; rb_enc_associate(str, enc); + OBJ_FREEZE(str); if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) { rb_raise(rb_eEncodingError, "invalid encoding symbol"); diff --git a/ruby.c b/ruby.c index 86cb0b08a5..93b12d87bf 100644 --- a/ruby.c +++ b/ruby.c @@ -1309,12 +1309,12 @@ process_options(int argc, char **argv, struct cmdline_options *opt) #if defined DOSISH || defined __CYGWIN__ translit_char(RSTRING_PTR(opt->script_name), '\\', '/'); #endif - rb_obj_freeze(opt->script_name); ruby_init_loadpath_safe(opt->safe_level); rb_enc_find_index("encdb"); lenc = rb_locale_encoding(); rb_enc_associate(rb_progname, lenc); + rb_obj_freeze(rb_progname); parser = rb_parser_new(); if (opt->dump & DUMP_BIT(yydebug)) { rb_parser_set_yydebug(parser, Qtrue); @@ -1342,6 +1342,7 @@ process_options(int argc, char **argv, struct cmdline_options *opt) opt->intern.enc.index = -1; } rb_enc_associate(opt->script_name, lenc); + rb_obj_freeze(opt->script_name); { long i; VALUE load_path = GET_VM()->load_path; @@ -1694,7 +1695,7 @@ void ruby_script(const char *name) { if (name) { - rb_progname = rb_obj_freeze(rb_external_str_new(name, strlen(name))); + rb_progname = rb_external_str_new(name, strlen(name)); rb_vm_set_progname(rb_progname); } } diff --git a/test/-ext-/string/test_enc_associate.rb b/test/-ext-/string/test_enc_associate.rb new file mode 100644 index 0000000000..edddfb4316 --- /dev/null +++ b/test/-ext-/string/test_enc_associate.rb @@ -0,0 +1,12 @@ +require 'test/unit' +require "-test-/string/string" + +class Test_StrEncAssociate < Test::Unit::TestCase + def test_frozen + s = Bug::String.new("abc") + s.force_encoding(Encoding::US_ASCII) + s.freeze + assert_raise(RuntimeError) {s.associate_encoding!(Encoding::US_ASCII)} + assert_raise(RuntimeError) {s.associate_encoding!(Encoding::UTF_8)} + end +end