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 <[email protected]>
+
+ * 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 <[email protected]>
* 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)}