summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--README.EXT17
-rw-r--r--README.EXT.ja17
-rw-r--r--eval.c67
-rw-r--r--ext/curses/curses.c6
-rw-r--r--gc.c3
-rw-r--r--node.h4
-rw-r--r--parse.y4
-rw-r--r--sample/test.rb34
9 files changed, 113 insertions, 56 deletions
diff --git a/ChangeLog b/ChangeLog
index 668bee3d3a..2f775e974b 100644
--- a/ChangeLog
+++ b/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
diff --git a/README.EXT b/README.EXT
index 4bbe1202e6..97e57934be 100644
--- a/README.EXT
+++ b/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
diff --git a/README.EXT.ja b/README.EXT.ja
index 0ef67497ce..f4681880b4 100644
--- a/README.EXT.ja
+++ b/README.EXT.ja
@@ -104,10 +104,19 @@ FIXNUMとNILに関してはより高速な判別マクロが用意されています.
います.それから,FIXNUMに限らずRubyのデータを整数に変換する
「NUM2INT()」というマクロがあります.このマクロはデータタイ
プのチェック無しで使えます(整数に変換できない場合には例外が
-発生する).
-
-同様にチェック無しで使える変換マクロはdoubleを取り出す
-「NUM2DBL()」とchar*を取り出す「STR2CSTR()」があります.
+発生する).同様にチェック無しで使える変換マクロはdoubleを
+取り出す「NUM2DBL()」があります。
+
+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はそのままキャスト(型変換)すれば構造体の
diff --git a/eval.c b/eval.c
index e59ad61e78..e166712ed0 100644
--- a/eval.c
+++ b/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);
}
diff --git a/ext/curses/curses.c b/ext/curses/curses.c
index fa29263bcd..a666cce897 100644
--- a/ext/curses/curses.c
+++ b/ext/curses/curses.c
@@ -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);
diff --git a/gc.c b/gc.c
index 6789c0d180..6c8e9f650e 100644
--- a/gc.c
+++ b/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();
}
diff --git a/node.h b/node.h
index da2f2f4f52..516618a7a5 100644
--- a/node.h
+++ b/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)
diff --git a/parse.y b/parse.y
index 8096d5d576..faea6c4639 100644
--- a/parse.y
+++ b/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;
}
diff --git a/sample/test.rb b/sample/test.rb
index fb7c0f6757..5c263090d0 100644
--- a/sample/test.rb
+++ b/sample/test.rb
@@ -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)}