ruby-changes:20521
From: nobu <ko1@a...>
Date: Sun, 17 Jul 2011 16:26:56 +0900 (JST)
Subject: [ruby-changes:20521] nobu:r32569 (trunk): * error.c (rb_check_trusted): new function to check an object is
nobu 2011-07-17 16:26:45 +0900 (Sun, 17 Jul 2011) New Revision: 32569 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=32569 Log: * error.c (rb_check_trusted): new function to check an object is trusted. * struct.c (rb_struct_modify), time.c (time_modify): check by the above function to show proper class names. [Bug #5036] Added files: trunk/t.rb Modified files: trunk/ChangeLog trunk/error.c trunk/include/ruby/intern.h trunk/struct.c trunk/test/ruby/test_struct.rb trunk/test/ruby/test_time.rb trunk/time.c Index: time.c =================================================================== --- time.c (revision 32568) +++ time.c (revision 32569) @@ -1876,8 +1876,7 @@ time_modify(VALUE time) { rb_check_frozen(time); - if (!OBJ_UNTRUSTED(time) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't modify Time"); + rb_check_trusted(time); } static wideval_t Index: include/ruby/intern.h =================================================================== --- include/ruby/intern.h (revision 32568) +++ include/ruby/intern.h (revision 32569) @@ -215,15 +215,24 @@ PRINTF_ARGS(void rb_compile_error_append(const char*, ...), 1, 2); NORETURN(void rb_load_fail(const char*)); NORETURN(void rb_error_frozen(const char*)); +void rb_error_untrusted(VALUE); void rb_check_frozen(VALUE); +void rb_check_trusted(VALUE); #define rb_check_frozen_internal(obj) do { \ VALUE frozen_obj = (obj); \ if (OBJ_FROZEN(frozen_obj)) { \ rb_error_frozen(rb_obj_classname(frozen_obj)); \ } \ } while (0) +#define rb_check_trusted_internal(obj) do { \ + VALUE untrusted_obj = (obj); \ + if (!OBJ_UNTRUSTED(untrusted_obj)) { \ + rb_error_untrusted(untrusted_obj); \ + } \ + } while (0) #ifdef __GNUC__ #define rb_check_frozen(obj) __extension__({rb_check_frozen_internal(obj);}) +#define rb_check_trusted(obj) __extension__({rb_check_trusted_internal(obj);}) #else static inline void rb_check_frozen_inline(VALUE obj) @@ -231,6 +240,12 @@ rb_check_frozen_internal(obj); } #define rb_check_frozen(obj) rb_check_frozen_inline(obj) +static inline void +rb_check_trusted_inline(VALUE obj) +{ + rb_check_trusted_internal(obj); +} +#define rb_check_trusted(obj) rb_check_trusted_inline(obj) #endif /* eval.c */ Index: ChangeLog =================================================================== --- ChangeLog (revision 32568) +++ ChangeLog (revision 32569) @@ -1,3 +1,11 @@ +Sun Jul 17 16:26:40 2011 Nobuyoshi Nakada <nobu@r...> + + * error.c (rb_check_trusted): new function to check an object is + trusted. + + * struct.c (rb_struct_modify), time.c (time_modify): check by the + above function to show proper class names. [Bug #5036] + Sun Jul 17 15:30:04 2011 Nobuyoshi Nakada <nobu@r...> * error.c (rb_warn_m): accept multiple args in like puts. rdoc Index: struct.c =================================================================== --- struct.c (revision 32568) +++ struct.c (revision 32569) @@ -153,8 +153,7 @@ rb_struct_modify(VALUE s) { rb_check_frozen(s); - if (!OBJ_UNTRUSTED(s) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't modify Struct"); + rb_check_trusted(s); } static VALUE Index: error.c =================================================================== --- error.c (revision 32568) +++ error.c (revision 32569) @@ -1715,6 +1715,22 @@ } void +rb_error_untrusted(VALUE obj) +{ + if (rb_safe_level() >= 4) { + rb_raise(rb_eSecurityError, "Insecure: can't modify %s", + rb_obj_classname(obj)); + } +} + +#undef rb_check_trusted +void +rb_check_trusted(VALUE obj) +{ + rb_check_trusted_internal(obj); +} + +void Init_syserr(void) { rb_eNOERROR = set_syserr(0, "NOERROR"); Index: t.rb =================================================================== --- t.rb (revision 0) +++ t.rb (revision 32569) @@ -0,0 +1,8 @@ +#! /usr/bin/ruby +tc = Class.new(Time) +tc.inspect +t = tc.now +proc do + $SAFE=4 + t.gmtime +end.call Property changes on: t.rb ___________________________________________________________________ Added: svn:eol-style + LF Added: svn:executable + * Index: test/ruby/test_struct.rb =================================================================== --- test/ruby/test_struct.rb (revision 32568) +++ test/ruby/test_struct.rb (revision 32569) @@ -1,5 +1,6 @@ require 'test/unit' require 'timeout' +require_relative 'envutil' class TestStruct < Test::Unit::TestCase def test_struct @@ -249,4 +250,17 @@ assert !x.eql?(z) } end + + def test_struct_subclass + bug5036 = '[ruby-dev:44122]' + st = Class.new(Struct) + s = st.new("S", :m).new + error = assert_raise(SecurityError) do + proc do + $SAFE = 4 + s.m = 1 + end.call + end + assert_equal("Insecure: can't modify #{st}::S", error.message, bug5036) + end end Index: test/ruby/test_time.rb =================================================================== --- test/ruby/test_time.rb (revision 32568) +++ test/ruby/test_time.rb (revision 32569) @@ -3,6 +3,7 @@ require 'delegate' require 'timeout' require 'delegate' +require_relative 'envutil' class TestTime < Test::Unit::TestCase def setup @@ -702,7 +703,7 @@ bug5012 = "[ruby-dev:44071]" t0 = Time.now - class <<t0; end + class << t0; end t1 = t0.getlocal def t0.m @@ -711,4 +712,18 @@ assert_raise(NoMethodError, bug5012) { t1.m } end + + def test_time_subclass + bug5036 = '[ruby-dev:44122]' + tc = Class.new(Time) + tc.inspect + t = tc.now + error = assert_raise(SecurityError) do + proc do + $SAFE = 4 + t.gmtime + end.call + end + assert_equal("Insecure: can't modify #{tc}", error.message, bug5036) + end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/