mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* eval.c (avalue_splat): new function to do unary * (splat)
operator. * eval.c (avalue_to_svalue,svalue_to_avalue,svalue_to_mrhs): do not use implicit "to_ary" conversion. * ext/curses/curses.c (GetWINDOW,GetMOUSE): add taint check. * ext/curses/curses.c (curses_init_screen): ditto. * ext/curses/curses.c (window_initialize): ditto. * gc.c (os_each_obj): prohibit ObjectSpace#each_object in safe mode ($SAFE >= 4). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3616 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									8478ba513f
								
							
						
					
					
						commit
						e9b5878c41
					
				
					 9 changed files with 112 additions and 55 deletions
				
			
		
							
								
								
									
										17
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								ChangeLog
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,20 @@
 | 
			
		|||
Wed Mar 26 13:19:32 2003  Yukihiro Matsumoto  <matz@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* eval.c (avalue_splat): new function to do unary * (splat)
 | 
			
		||||
	  operator.
 | 
			
		||||
 | 
			
		||||
	* eval.c (avalue_to_svalue,svalue_to_avalue,svalue_to_mrhs): do
 | 
			
		||||
	  not use implicit "to_ary" conversion.
 | 
			
		||||
 | 
			
		||||
	* ext/curses/curses.c (GetWINDOW,GetMOUSE): add taint check.
 | 
			
		||||
 | 
			
		||||
	* ext/curses/curses.c (curses_init_screen): ditto.
 | 
			
		||||
 | 
			
		||||
	* ext/curses/curses.c (window_initialize): ditto.
 | 
			
		||||
 | 
			
		||||
	* gc.c (os_each_obj): prohibit ObjectSpace#each_object in safe
 | 
			
		||||
	  mode ($SAFE >= 4).
 | 
			
		||||
 | 
			
		||||
Tue Mar 25 23:26:02 2003  Yukihiro Matsumoto  <matz@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* signal.c (trap): return "DEFAULT" and "IGNORE" respectively for
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								README.EXT
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								README.EXT
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -94,9 +94,20 @@ The T_FIXNUM data is a 31bit length fixed integer (63bit length on
 | 
			
		|||
some machines), which can be convert to a C integer by using the
 | 
			
		||||
FIX2INT() macro.  There is also NUM2INT() which converts any Ruby
 | 
			
		||||
numbers into C integers.  The NUM2INT() macro includes a type check, so
 | 
			
		||||
an exception will be raised if the conversion failed. There are also
 | 
			
		||||
a macro NUM2DBL() to retrieve the double float value and STR2CSTR() is
 | 
			
		||||
useful to get the string as char*.
 | 
			
		||||
an exception will be raised if the conversion failed.  NUM2DBL() can
 | 
			
		||||
be used to retrieve the double float value in same way.
 | 
			
		||||
 | 
			
		||||
To get char* from a VALUE, version 1.7 recommend to use new macros
 | 
			
		||||
StringValue() and StringValuePtr().  StringValue(var) replaces var's
 | 
			
		||||
value to the result of "var.to_str()".  StringValuePtr(var) does same
 | 
			
		||||
replacement and returns char* representation of var.  These macros
 | 
			
		||||
will skip the replacement if var is a String.  Notice that the macros
 | 
			
		||||
requires to take only lvalue as their argument, to change the value
 | 
			
		||||
of var in the replacement. 
 | 
			
		||||
 | 
			
		||||
In version 1.6 or earlier, STR2CSTR() was used to do same thing
 | 
			
		||||
but now it is obsoleted in version 1.7 because of STR2CSTR() has
 | 
			
		||||
a risk of dangling pointer problem in to_str() impliclit conversion.
 | 
			
		||||
 | 
			
		||||
Other data types have corresponding C structures, e.g. struct RArray
 | 
			
		||||
for T_ARRAY etc. The VALUE of the type which has corresponding structure
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,10 +104,19 @@ FIXNUM
 | 
			
		|||
います.それから,FIXNUMに限らずRubyのデータを整数に変換する
 | 
			
		||||
「NUM2INT()」というマクロがあります.このマクロはデータタイ
 | 
			
		||||
プのチェック無しで使えます(整数に変換できない場合には例外が
 | 
			
		||||
発生する).
 | 
			
		||||
発生する).同様にチェック無しで使える変換マクロはdoubleを
 | 
			
		||||
取り出す「NUM2DBL()」があります。
 | 
			
		||||
 | 
			
		||||
同様にチェック無しで使える変換マクロはdoubleを取り出す
 | 
			
		||||
「NUM2DBL()」とchar*を取り出す「STR2CSTR()」があります.
 | 
			
		||||
char* を取り出す場合、version 1.6 以前では「STR2CSTR()」と
 | 
			
		||||
いうマクロを使っていましたが、これは to_str() による暗黙の
 | 
			
		||||
型変換結果が GC される可能性があるため、version 1.7 以降では
 | 
			
		||||
obsolete となり、代わりに StringValue() と StringValuePtr()
 | 
			
		||||
を使う事を推奨しています。StringValue(var) は var が String
 | 
			
		||||
 であれば何もせず、そうでなければ var を var.to_str() の結果に
 | 
			
		||||
置き換えるマクロ、StringValuePtr(var) は同様に var を置き換え
 | 
			
		||||
てから var の文字列表現に対する char* を返すマクロです。var の
 | 
			
		||||
内容を直接置き換える処理が入るので、var は lvalue である必要が
 | 
			
		||||
あります。
 | 
			
		||||
 | 
			
		||||
それ以外のデータタイプは対応するCの構造体があります.対応す
 | 
			
		||||
る構造体のあるVALUEはそのままキャスト(型変換)すれば構造体の
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										67
									
								
								eval.c
									
										
									
									
									
								
							
							
						
						
									
										67
									
								
								eval.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2201,28 +2201,23 @@ static VALUE
 | 
			
		|||
avalue_to_svalue(v)
 | 
			
		||||
    VALUE v;
 | 
			
		||||
{
 | 
			
		||||
    VALUE tmp;
 | 
			
		||||
 | 
			
		||||
    if (v == Qundef) return v;
 | 
			
		||||
    tmp = rb_check_array_type(v);
 | 
			
		||||
    if (NIL_P(tmp)) {
 | 
			
		||||
    if (TYPE(v) != T_ARRAY) {
 | 
			
		||||
	return v;
 | 
			
		||||
    }
 | 
			
		||||
    v = tmp;
 | 
			
		||||
    if (RARRAY(v)->len == 0) {
 | 
			
		||||
	return Qundef;
 | 
			
		||||
    }
 | 
			
		||||
    if (RARRAY(v)->len == 1) {
 | 
			
		||||
	tmp = rb_check_array_type(RARRAY(v)->ptr[0]);
 | 
			
		||||
	if (NIL_P(tmp)) {
 | 
			
		||||
	    return RARRAY(v)->ptr[0];
 | 
			
		||||
	VALUE tmp = RARRAY(v)->ptr[0];
 | 
			
		||||
	if (TYPE(tmp) != T_ARRAY) {
 | 
			
		||||
	    return tmp;
 | 
			
		||||
	}
 | 
			
		||||
	if (RARRAY(tmp)->len > 1) {
 | 
			
		||||
	    return v;
 | 
			
		||||
	}
 | 
			
		||||
	return tmp;
 | 
			
		||||
    }
 | 
			
		||||
    return tmp;
 | 
			
		||||
    return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
| 
						 | 
				
			
			@ -2232,40 +2227,29 @@ svalue_to_avalue(v)
 | 
			
		|||
    VALUE tmp;
 | 
			
		||||
 | 
			
		||||
    if (v == Qundef) return rb_ary_new2(0);
 | 
			
		||||
    tmp = rb_check_array_type(v);
 | 
			
		||||
 | 
			
		||||
    if (NIL_P(tmp)) {
 | 
			
		||||
    if (TYPE(v) != T_ARRAY) {
 | 
			
		||||
	return rb_ary_new3(1, v);
 | 
			
		||||
    }
 | 
			
		||||
    v = tmp;
 | 
			
		||||
    if (RARRAY(v)->len == 1) {
 | 
			
		||||
	tmp = rb_check_array_type(RARRAY(v)->ptr[0]);
 | 
			
		||||
	if (NIL_P(tmp)) return rb_ary_new3(1, v);
 | 
			
		||||
	if (RARRAY(tmp)->len > 1) return v;
 | 
			
		||||
	return tmp;
 | 
			
		||||
	tmp = RARRAY(v)->ptr[0];
 | 
			
		||||
	if (TYPE(tmp) == T_ARRAY && RARRAY(tmp)->len > 1)
 | 
			
		||||
	    return v;
 | 
			
		||||
	return rb_ary_new3(1, v);
 | 
			
		||||
    }
 | 
			
		||||
    return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
avalue_to_mrhs(v)
 | 
			
		||||
avalue_splat(v)
 | 
			
		||||
    VALUE v;
 | 
			
		||||
{
 | 
			
		||||
    VALUE tmp;
 | 
			
		||||
 | 
			
		||||
    if (v == Qundef) return v;
 | 
			
		||||
    tmp = rb_check_array_type(v);
 | 
			
		||||
    if (NIL_P(tmp)) {
 | 
			
		||||
	return v;
 | 
			
		||||
    }
 | 
			
		||||
    v = tmp;
 | 
			
		||||
    if (RARRAY(v)->len == 0) {
 | 
			
		||||
	return Qundef;
 | 
			
		||||
    }
 | 
			
		||||
    if (RARRAY(v)->len == 1) {
 | 
			
		||||
	return RARRAY(v)->ptr[0];
 | 
			
		||||
    }
 | 
			
		||||
    return tmp;
 | 
			
		||||
    return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
| 
						 | 
				
			
			@ -2273,18 +2257,15 @@ svalue_to_mrhs(v, lhs)
 | 
			
		|||
    VALUE v;
 | 
			
		||||
    NODE *lhs;
 | 
			
		||||
{
 | 
			
		||||
    VALUE tmp;
 | 
			
		||||
 | 
			
		||||
    if (v == Qundef) return rb_ary_new2(0);
 | 
			
		||||
    tmp = rb_check_array_type(v);
 | 
			
		||||
 | 
			
		||||
    if (NIL_P(tmp)) {
 | 
			
		||||
    if (TYPE(v) != T_ARRAY) {
 | 
			
		||||
	return rb_ary_new3(1, v);
 | 
			
		||||
    }
 | 
			
		||||
    if (!lhs && RARRAY(tmp)->len <= 1) {
 | 
			
		||||
	return rb_ary_new3(1, tmp);
 | 
			
		||||
    /* no lhs means splat lhs only */
 | 
			
		||||
    if (!lhs && RARRAY(v)->len <= 1) {
 | 
			
		||||
	return rb_ary_new3(1, v);
 | 
			
		||||
    }
 | 
			
		||||
    return tmp;
 | 
			
		||||
    return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
| 
						 | 
				
			
			@ -2670,8 +2651,16 @@ rb_eval(self, n)
 | 
			
		|||
	result = rb_ary_to_ary(rb_eval(self, node->nd_head));
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
      case NODE_REXPAND:
 | 
			
		||||
	result = avalue_to_mrhs(rb_eval(self, node->nd_head));
 | 
			
		||||
      case NODE_SPLAT:
 | 
			
		||||
        {
 | 
			
		||||
	    VALUE tmp;
 | 
			
		||||
 | 
			
		||||
	    result = rb_eval(self, node->nd_head);
 | 
			
		||||
	    tmp = rb_check_array_type(result);
 | 
			
		||||
	    if (!NIL_P(tmp)) {
 | 
			
		||||
		result = avalue_splat(tmp);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
      case NODE_SVALUE:
 | 
			
		||||
| 
						 | 
				
			
			@ -3982,7 +3971,7 @@ rb_yield_0(val, self, klass, pcall, avalue)
 | 
			
		|||
		massign(self, block->var, val, pcall);
 | 
			
		||||
	    }
 | 
			
		||||
	    else {
 | 
			
		||||
		if (avalue) val = avalue_to_mrhs(val);
 | 
			
		||||
		if (avalue) val = avalue_splat(val);
 | 
			
		||||
		if (val == Qundef) val = Qnil;
 | 
			
		||||
		assign(self, block->var, val, pcall);
 | 
			
		||||
	    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -75,6 +75,8 @@ no_window()
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#define GetWINDOW(obj, winp) do {\
 | 
			
		||||
    if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
 | 
			
		||||
	rb_raise(rb_eSecurityError, "Insecure: operation on untainted window");\
 | 
			
		||||
    Data_Get_Struct(obj, struct windata, winp);\
 | 
			
		||||
    if (winp->window == 0) no_window();\
 | 
			
		||||
} while (0)
 | 
			
		||||
| 
						 | 
				
			
			@ -113,6 +115,7 @@ prep_window(class, window)
 | 
			
		|||
static VALUE
 | 
			
		||||
curses_init_screen()
 | 
			
		||||
{
 | 
			
		||||
    rb_secure(4);
 | 
			
		||||
    if (rb_stdscr) return rb_stdscr;
 | 
			
		||||
    initscr();
 | 
			
		||||
    if (stdscr == 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -593,6 +596,8 @@ no_mevent()
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#define GetMOUSE(obj, data) do {\
 | 
			
		||||
    if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
 | 
			
		||||
	rb_raise(rb_eSecurityError, "Insecure: operation on untainted mouse");\
 | 
			
		||||
    Data_Get_Struct(obj, struct mousedata, data);\
 | 
			
		||||
    if (data->mevent == 0) no_mevent();\
 | 
			
		||||
} while (0)
 | 
			
		||||
| 
						 | 
				
			
			@ -677,6 +682,7 @@ window_initialize(obj, h, w, top, left)
 | 
			
		|||
    struct windata *winp;
 | 
			
		||||
    WINDOW *window;
 | 
			
		||||
 | 
			
		||||
    rb_secure(4);
 | 
			
		||||
    curses_init_screen();
 | 
			
		||||
    Data_Get_Struct(obj, struct windata, winp);
 | 
			
		||||
    if (winp->window) delwin(winp->window);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								gc.c
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								gc.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -705,6 +705,8 @@ rb_gc_mark(ptr)
 | 
			
		|||
	  case NODE_YIELD:
 | 
			
		||||
	  case NODE_COLON2:
 | 
			
		||||
	  case NODE_ARGS:
 | 
			
		||||
	  case NODE_SPLAT:
 | 
			
		||||
	  case NODE_SVALUE:
 | 
			
		||||
	    ptr = (VALUE)obj->as.node.u1.node;
 | 
			
		||||
	    goto again;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1377,6 +1379,7 @@ os_each_obj(argc, argv)
 | 
			
		|||
{
 | 
			
		||||
    VALUE of;
 | 
			
		||||
 | 
			
		||||
    rb_secure(4);
 | 
			
		||||
    if (rb_scan_args(argc, argv, "01", &of) == 0) {
 | 
			
		||||
	return os_live_obj();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								node.h
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								node.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -89,7 +89,7 @@ enum node_type {
 | 
			
		|||
    NODE_ARGSPUSH,
 | 
			
		||||
    NODE_RESTARY,
 | 
			
		||||
    NODE_RESTARY2,
 | 
			
		||||
    NODE_REXPAND,
 | 
			
		||||
    NODE_SPLAT,
 | 
			
		||||
    NODE_SVALUE,
 | 
			
		||||
    NODE_BLOCK_ARG,
 | 
			
		||||
    NODE_BLOCK_PASS,
 | 
			
		||||
| 
						 | 
				
			
			@ -309,7 +309,7 @@ typedef struct RNode {
 | 
			
		|||
#define NEW_ARGSPUSH(a,b) rb_node_newnode(NODE_ARGSPUSH,a,b,0)
 | 
			
		||||
#define NEW_RESTARY(a) rb_node_newnode(NODE_RESTARY,a,0,0)
 | 
			
		||||
#define NEW_RESTARY2(a) rb_node_newnode(NODE_RESTARY2,a,0,0)
 | 
			
		||||
#define NEW_REXPAND(a) rb_node_newnode(NODE_REXPAND,a,0,0)
 | 
			
		||||
#define NEW_SPLAT(a) rb_node_newnode(NODE_SPLAT,a,0,0)
 | 
			
		||||
#define NEW_SVALUE(a) rb_node_newnode(NODE_SVALUE,a,0,0)
 | 
			
		||||
#define NEW_BLOCK_ARG(v) rb_node_newnode(NODE_BLOCK_ARG,v,0,local_cnt(v))
 | 
			
		||||
#define NEW_BLOCK_PASS(b) rb_node_newnode(NODE_BLOCK_PASS,0,b,0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								parse.y
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								parse.y
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1385,7 +1385,7 @@ mrhs		: args ',' arg_value
 | 
			
		|||
		    }
 | 
			
		||||
		| tSTAR arg_value
 | 
			
		||||
		    {
 | 
			
		||||
			$$ = NEW_REXPAND($2);
 | 
			
		||||
			$$ = NEW_SPLAT($2);
 | 
			
		||||
		    }
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5314,7 +5314,7 @@ ret_args(node)
 | 
			
		|||
	}
 | 
			
		||||
    }
 | 
			
		||||
    if (node && nd_type(node) == NODE_RESTARY) {
 | 
			
		||||
	nd_set_type(node, NODE_REXPAND);
 | 
			
		||||
	nd_set_type(node, NODE_SPLAT);
 | 
			
		||||
    }
 | 
			
		||||
    return node;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -248,13 +248,33 @@ f = lambda {|r,*l| test_ok([] == r); test_ok([1] == l)}
 | 
			
		|||
f.call([], *[1])
 | 
			
		||||
f.yield([], *[1])
 | 
			
		||||
 | 
			
		||||
a = [42,55]
 | 
			
		||||
lambda{|x| test_ok([42,55] == x)}.call(a)
 | 
			
		||||
lambda{|x,| test_ok([42,55] == x)}.call(a)
 | 
			
		||||
lambda{|*x| test_ok([[42,55]] == x)}.call(a)
 | 
			
		||||
 | 
			
		||||
f = lambda{|x| x}
 | 
			
		||||
test_ok(f.call(42) == 42)
 | 
			
		||||
test_ok(f.call([42]) == [42])
 | 
			
		||||
test_ok(f.call([[42]]) == [[42]])
 | 
			
		||||
test_ok(f.call([42,55]) == [42,55])
 | 
			
		||||
test_ok(f.call(42,55) == [42,55])
 | 
			
		||||
 | 
			
		||||
f = lambda{|x,| x}
 | 
			
		||||
test_ok(f.call(42) == 42)
 | 
			
		||||
test_ok(f.call([42]) == [42])
 | 
			
		||||
test_ok(f.call([[42]]) == [[42]])
 | 
			
		||||
test_ok(f.call([42,55]) == [42,55])
 | 
			
		||||
 | 
			
		||||
f = lambda{|*x| x}
 | 
			
		||||
test_ok(f.call(42) == [42])
 | 
			
		||||
test_ok(f.call([42]) == [[42]])
 | 
			
		||||
test_ok(f.call([[42]]) == [[[42]]])
 | 
			
		||||
test_ok(f.call([42,55]) == [[42,55]])
 | 
			
		||||
test_ok(f.call(42,55) == [42,55])
 | 
			
		||||
 | 
			
		||||
a,=*[1]
 | 
			
		||||
test_ok(a == 1)
 | 
			
		||||
a,=*[[1]]
 | 
			
		||||
test_ok(a == 1)
 | 
			
		||||
a,=*[[[1]]]
 | 
			
		||||
test_ok(a == [1])
 | 
			
		||||
 | 
			
		||||
a = loop do break; end; test_ok(a == nil)
 | 
			
		||||
a = loop do break nil; end; test_ok(a == nil)
 | 
			
		||||
| 
						 | 
				
			
			@ -905,10 +925,12 @@ class IterTest
 | 
			
		|||
  def each8; @body.each {|x| yield(x) } end
 | 
			
		||||
 | 
			
		||||
  def f(a)
 | 
			
		||||
    test_ok(a == [1])
 | 
			
		||||
    a
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
IterTest.new(nil).method(:f).to_proc.call([1])
 | 
			
		||||
test_ok(IterTest.new(nil).method(:f).to_proc.call([1]) == [1])
 | 
			
		||||
m = /\w+/.match("abc")
 | 
			
		||||
test_ok(IterTest.new(nil).method(:f).to_proc.call([m]) == [m])
 | 
			
		||||
 | 
			
		||||
IterTest.new([0]).each0 {|x| test_ok(x == 0)}
 | 
			
		||||
IterTest.new([1]).each1 {|x| test_ok(x == 1)}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue