* 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:
matz 2003-03-26 07:01:14 +00:00
Родитель 8478ba513f
Коммит e9b5878c41
9 изменённых файлов: 112 добавлений и 55 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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
Просмотреть файл

@ -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
Просмотреть файл

@ -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
Просмотреть файл

@ -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)

Просмотреть файл

@ -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)}