From 73bb30c2f4dba7c8da091ec5c5308d6dacf5f52f Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 21 Nov 2016 16:31:47 -0500 Subject: Copy over INSTANCE_TT when duping class --- test/t/kernel.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'test/t/kernel.rb') diff --git a/test/t/kernel.rb b/test/t/kernel.rb index 927166283..d240e59dc 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -221,6 +221,14 @@ assert('Kernel#dup', '15.3.1.3.9') do assert_false c.respond_to?(:test) end +assert('Kernel#dup class') do + assert_nothing_raised do + Array.dup.new(200) + Range.dup.new(2, 3) + String.dup.new("a"*50) + end +end + # Kernel#eval is provided by mruby-eval mrbgem '15.3.1.3.12' assert('Kernel#extend', '15.3.1.3.13') do -- cgit v1.2.3 From 9c61e1cd87aca3646fe39a6d53223efdcb11e250 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 28 Nov 2016 15:04:27 -0500 Subject: Use mrb_ptr instead of mrb_cptr in Kernel#to_s This is to avoid segfault when WORD_BOXING is enabled Reported by https://hackerone.com/brakhane --- src/object.c | 2 +- test/t/kernel.rb | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'test/t/kernel.rb') diff --git a/src/object.c b/src/object.c index f76ee68a2..eb2c23e63 100644 --- a/src/object.c +++ b/src/object.c @@ -444,7 +444,7 @@ mrb_any_to_s(mrb_state *mrb, mrb_value obj) mrb_str_cat_lit(mrb, str, "#<"); mrb_str_cat_cstr(mrb, str, cname); mrb_str_cat_lit(mrb, str, ":"); - mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(obj))); + mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_ptr(obj))); mrb_str_cat_lit(mrb, str, ">"); return str; diff --git a/test/t/kernel.rb b/test/t/kernel.rb index d240e59dc..e59bd6a10 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -520,6 +520,21 @@ assert('Kernel#to_s', '15.3.1.3.46') do assert_equal to_s.class, String end +assert('Kernel#to_s on primitives') do + begin + Fixnum.alias_method :to_s_, :to_s + Fixnum.remove_method :to_s + + assert_nothing_raised do + # segfaults if mrb_cptr is used + 1.to_s + end + ensure + Fixnum.alias_method :to_s, :to_s_ + Fixnum.remove_method :to_s_ + end +end + assert('Kernel.local_variables', '15.3.1.2.7') do a, b = 0, 1 a += b -- cgit v1.2.3 From 10bb7ad693e7c7443de924a39c1fedb4461108ba Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Sun, 11 Dec 2016 01:45:38 +0900 Subject: Implement Object#freeze --- include/mruby/class.h | 1 + include/mruby/object.h | 4 ++++ include/mruby/string.h | 5 ----- src/array.c | 4 ++++ src/hash.c | 7 +++++-- src/kernel.c | 10 ++++++++++ src/string.c | 15 ++------------- test/t/array.rb | 7 +++++++ test/t/hash.rb | 7 +++++++ test/t/kernel.rb | 5 +++++ 10 files changed, 45 insertions(+), 20 deletions(-) (limited to 'test/t/kernel.rb') diff --git a/include/mruby/class.h b/include/mruby/class.h index 246e82e59..ce953af3b 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -52,6 +52,7 @@ mrb_class(mrb_state *mrb, mrb_value v) } // TODO: figure out where to put user flags +#define MRB_FLAG_IS_FROZEN (1 << 18) #define MRB_FLAG_IS_PREPENDED (1 << 19) #define MRB_FLAG_IS_ORIGIN (1 << 20) #define MRB_CLASS_ORIGIN(c) do {\ diff --git a/include/mruby/object.h b/include/mruby/object.h index 9fbfe34f3..da44027e1 100644 --- a/include/mruby/object.h +++ b/include/mruby/object.h @@ -22,6 +22,10 @@ struct RBasic { }; #define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v))) +#define RBASIC_FROZEN_P(o) ((o)->flags & MRB_FLAG_IS_FROZEN) +#define RBASIC_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FLAG_IS_FROZEN) +#define RBASIC_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FLAG_IS_FROZEN) + struct RObject { MRB_OBJECT_HEADER; struct iv_tbl *iv; diff --git a/include/mruby/string.h b/include/mruby/string.h index b30c1ed98..9ccf8f187 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -62,10 +62,6 @@ struct RString { #define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE) #define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE) -#define RSTR_FROZEN_P(s) ((s)->flags & MRB_STR_FROZEN) -#define RSTR_SET_FROZEN_FLAG(s) ((s)->flags |= MRB_STR_FROZEN) -#define RSTR_UNSET_FROZEN_FLAG(s) ((s)->flags &= ~MRB_STR_FROZEN) - /* * Returns a pointer from a Ruby string */ @@ -80,7 +76,6 @@ MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*); #define MRB_STR_SHARED 1 #define MRB_STR_NOFREE 2 -#define MRB_STR_FROZEN 4 #define MRB_STR_NO_UTF 8 #define MRB_STR_EMBED 16 #define MRB_STR_EMBED_LEN_MASK 0x3e0 diff --git a/src/array.c b/src/array.c index f6599bd5b..c6bac7b47 100644 --- a/src/array.c +++ b/src/array.c @@ -108,6 +108,10 @@ ary_fill_with_nil(mrb_value *ptr, mrb_int size) static void ary_modify(mrb_state *mrb, struct RArray *a) { + if (RBASIC_FROZEN_P(a)) { + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen array"); + } + if (ARY_SHARED_P(a)) { mrb_shared_array *shared = a->aux.shared; diff --git a/src/hash.c b/src/hash.c index 93fe656e0..d0e865b5c 100644 --- a/src/hash.c +++ b/src/hash.c @@ -98,9 +98,9 @@ static void mrb_hash_modify(mrb_state *mrb, mrb_value hash); static inline mrb_value mrb_hash_ht_key(mrb_state *mrb, mrb_value key) { - if (mrb_string_p(key) && !RSTR_FROZEN_P(mrb_str_ptr(key))) { + if (mrb_string_p(key) && !RBASIC_FROZEN_P(mrb_str_ptr(key))) { key = mrb_str_dup(mrb, key); - RSTR_SET_FROZEN_FLAG(mrb_str_ptr(key)); + RBASIC_SET_FROZEN_FLAG(mrb_str_ptr(key)); } return key; } @@ -278,6 +278,9 @@ mrb_hash_tbl(mrb_state *mrb, mrb_value hash) static void mrb_hash_modify(mrb_state *mrb, mrb_value hash) { + if (RBASIC_FROZEN_P(mrb_hash_ptr(hash))) { + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen hash"); + } mrb_hash_tbl(mrb, hash); } diff --git a/src/kernel.c b/src/kernel.c index c63e05596..78e57a17a 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -450,6 +450,15 @@ mrb_obj_extend_m(mrb_state *mrb, mrb_value self) return mrb_obj_extend(mrb, argc, argv, self); } +static mrb_value +mrb_obj_freeze(mrb_state *mrb, mrb_value self) +{ + struct RBasic *b = mrb_basic_ptr(self); + + RBASIC_SET_FROZEN_FLAG(b); + return self; +} + /* 15.3.1.3.15 */ /* * call-seq: @@ -1124,6 +1133,7 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "eql?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.10 */ mrb_define_method(mrb, krn, "equal?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */ mrb_define_method(mrb, krn, "extend", mrb_obj_extend_m, MRB_ARGS_ANY()); /* 15.3.1.3.13 */ + mrb_define_method(mrb, krn, "freeze", mrb_obj_freeze, MRB_ARGS_NONE()); mrb_define_method(mrb, krn, "global_variables", mrb_f_global_variables, MRB_ARGS_NONE()); /* 15.3.1.3.14 */ mrb_define_method(mrb, krn, "hash", mrb_obj_hash, MRB_ARGS_NONE()); /* 15.3.1.3.15 */ mrb_define_method(mrb, krn, "initialize_copy", mrb_obj_init_copy, MRB_ARGS_REQ(1)); /* 15.3.1.3.16 */ diff --git a/src/string.c b/src/string.c index a4f8085ec..7234ecf2b 100644 --- a/src/string.c +++ b/src/string.c @@ -501,7 +501,7 @@ str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset) static void check_frozen(mrb_state *mrb, struct RString *s) { - if (RSTR_FROZEN_P(s)) { + if (RBASIC_FROZEN_P(s)) { mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string"); } } @@ -700,15 +700,6 @@ mrb_str_modify(mrb_state *mrb, struct RString *s) } } -static mrb_value -mrb_str_freeze(mrb_state *mrb, mrb_value str) -{ - struct RString *s = mrb_str_ptr(str); - - RSTR_SET_FROZEN_FLAG(s); - return str; -} - MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len) { @@ -2217,7 +2208,7 @@ mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr) char *p = RSTR_PTR(ps); if (!p || p[len] != '\0') { - if (RSTR_FROZEN_P(ps)) { + if (RBASIC_FROZEN_P(ps)) { *ptr = str = mrb_str_dup(mrb, str); ps = mrb_str_ptr(str); } @@ -2746,8 +2737,6 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */ mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */ mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE()); - - mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE()); } /* diff --git a/test/t/array.rb b/test/t/array.rb index 9cc2f64ad..cf7ed4704 100644 --- a/test/t/array.rb +++ b/test/t/array.rb @@ -373,3 +373,10 @@ assert("Array#rindex") do $a = [2, 3, 4, 5, 6, 7, 8, 9, 10, Sneaky.new] assert_equal 0, $a.rindex(1) end + +assert('Array#freeze') do + a = [].freeze + assert_raise(RuntimeError) do + a[0] = 1 + end +end diff --git a/test/t/hash.rb b/test/t/hash.rb index f076db8e5..c63b8c009 100644 --- a/test/t/hash.rb +++ b/test/t/hash.rb @@ -366,3 +366,10 @@ assert('Hash#rehash') do h.rehash assert_equal("b", h[[:b]]) end + +assert('Hash#freeze') do + h = {}.freeze + assert_raise(RuntimeError) do + h[:a] = 'b' + end +end diff --git a/test/t/kernel.rb b/test/t/kernel.rb index e59bd6a10..42abed9df 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -257,6 +257,11 @@ assert('Kernel#extend works on toplevel', '15.3.1.3.13') do assert_true respond_to?(:test_method) end +assert('Kernel#freeze') do + obj = Object.new + assert_equal obj, obj.freeze +end + assert('Kernel#global_variables', '15.3.1.3.14') do assert_equal Array, global_variables.class end -- cgit v1.2.3 From 5c1c002ac2983fef8ef3254e2d2f3e016918c3cd Mon Sep 17 00:00:00 2001 From: ksss Date: Sat, 24 Dec 2016 22:54:52 +0900 Subject: Fix segv when primitive value Fix #3352 --- src/kernel.c | 18 ++++++++++++++++-- test/t/kernel.rb | 3 ++- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'test/t/kernel.rb') diff --git a/src/kernel.c b/src/kernel.c index a5166deb2..5e44d73b4 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -453,9 +453,23 @@ mrb_obj_extend_m(mrb_state *mrb, mrb_value self) static mrb_value mrb_obj_freeze(mrb_state *mrb, mrb_value self) { - struct RBasic *b = mrb_basic_ptr(self); + struct RBasic *b; + + switch (mrb_type(self)) { + case MRB_TT_FALSE: + case MRB_TT_TRUE: + case MRB_TT_FIXNUM: + case MRB_TT_SYMBOL: + case MRB_TT_FLOAT: + return self; + default: + break; + } - MRB_SET_FROZEN_FLAG(b); + b = mrb_basic_ptr(self); + if (!MRB_FROZEN_P(b)) { + MRB_SET_FROZEN_FLAG(b); + } return self; } diff --git a/test/t/kernel.rb b/test/t/kernel.rb index 42abed9df..ca4b73907 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -260,6 +260,8 @@ end assert('Kernel#freeze') do obj = Object.new assert_equal obj, obj.freeze + assert_equal 0, 0.freeze + assert_equal :a, :a.freeze end assert('Kernel#global_variables', '15.3.1.3.14') do @@ -620,4 +622,3 @@ assert('stack extend') do assert_equal 6, recurse(0, 5) end - -- cgit v1.2.3 From bd72dba8c05056693e42c74b35d90691221f0d0d Mon Sep 17 00:00:00 2001 From: ksss Date: Mon, 6 Feb 2017 11:04:42 +0900 Subject: Kernel#local_variables: Make result array unique --- src/kernel.c | 11 ++++++----- test/t/kernel.rb | 7 +++---- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'test/t/kernel.rb') diff --git a/src/kernel.c b/src/kernel.c index 5ca1736c3..8b00d701b 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -1106,8 +1107,8 @@ mrb_obj_ceqq(mrb_state *mrb, mrb_value self) static mrb_value mrb_local_variables(mrb_state *mrb, mrb_value self) { - mrb_value ret; struct RProc *proc; + mrb_value vars; struct mrb_irep *irep; size_t i; @@ -1121,10 +1122,10 @@ mrb_local_variables(mrb_state *mrb, mrb_value self) if (!irep->lv) { return mrb_ary_new(mrb); } - ret = mrb_ary_new_capa(mrb, irep->nlocals - 1); + vars = mrb_hash_new(mrb); for (i = 0; i + 1 < irep->nlocals; ++i) { if (irep->lv[i].name) { - mrb_ary_push(mrb, ret, mrb_symbol_value(irep->lv[i].name)); + mrb_hash_set(mrb, vars, mrb_symbol_value(irep->lv[i].name), mrb_true_value()); } } if (proc->env) { @@ -1137,7 +1138,7 @@ mrb_local_variables(mrb_state *mrb, mrb_value self) if (irep->lv) { for (i = 0; i + 1 < irep->nlocals; ++i) { if (irep->lv[i].name) { - mrb_ary_push(mrb, ret, mrb_symbol_value(irep->lv[i].name)); + mrb_hash_set(mrb, vars, mrb_symbol_value(irep->lv[i].name), mrb_true_value()); } } } @@ -1146,7 +1147,7 @@ mrb_local_variables(mrb_state *mrb, mrb_value self) } } - return ret; + return mrb_hash_keys(mrb, vars); } void diff --git a/test/t/kernel.rb b/test/t/kernel.rb index ca4b73907..aff2dd461 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -549,11 +549,10 @@ assert('Kernel.local_variables', '15.3.1.2.7') do vars = Kernel.local_variables.sort assert_equal [:a, :b, :vars], vars - Proc.new { + assert_equal [:a, :b, :c, :vars], Proc.new { |a, b| c = 2 - vars = Kernel.local_variables.sort - assert_equal [:a, :b, :c, :vars], vars - }.call + Kernel.local_variables.sort + }.call(-1, -2) end assert('Kernel#!=') do -- cgit v1.2.3