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…
Reference in a new issue