summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-06-19 04:36:34 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-06-19 04:36:34 +0000
commit9be426a0ec6ec98b61a7d99f2d77d5fdf79a3837 (patch)
tree0c70d582217d4ecf4ec7c05f5ad56d78eed47257
parente7392b3f844b7fe2517d8c671102dcc886a96edb (diff)
* eval.c (rb_f_require): searches ".rb" and ".so" at the same
time. previous behavior (search ".rb", then ".so") has a security risk (ruby-bugs#PR140). * regex.c (re_compile_pattern): avoid pushing unnecessary option_set. * eval.c (rb_load): tainted string is OK if wrapped *and* $SAFE >= 4. * eval.c (rb_thread_start_0): should not nail down higher blocks before preserving original context (i.e. should not alter original context). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_6@1527 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog22
-rw-r--r--eval.c42
-rw-r--r--file.c91
-rw-r--r--io.c9
-rw-r--r--regex.c58
5 files changed, 164 insertions, 58 deletions
diff --git a/ChangeLog b/ChangeLog
index 4a6297576e..b950c0bff5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+Mon Jun 18 17:38:50 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_f_require): searches ".rb" and ".so" at the same
+ time. previous behavior (search ".rb", then ".so") has a
+ security risk (ruby-bugs#PR140).
+
+Mon Jun 18 00:43:20 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (re_compile_pattern): avoid pushing unnecessary
+ option_set.
+
+Sat Jun 16 10:58:48 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_load): tainted string is OK if wrapped *and*
+ $SAFE >= 4.
+
+Thu Jun 14 16:27:07 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_start_0): should not nail down higher blocks
+ before preserving original context (i.e. should not alter
+ original context).
+
Tue Jun 12 14:24:02 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
* lib/mkmf.rb: target_prefix is only for installation, not for
diff --git a/eval.c b/eval.c
index ad0de6a38d..7478161c93 100644
--- a/eval.c
+++ b/eval.c
@@ -5128,7 +5128,12 @@ rb_load(fname, wrap)
NODE *saved_cref = ruby_cref;
TMP_PROTECT;
- Check_SafeStr(fname);
+ if (wrap && ruby_safe_level >= 4) {
+ Check_Type(fname, T_STRING);
+ }
+ else {
+ Check_SafeStr(fname);
+ }
file = rb_find_file(RSTRING(fname)->ptr);
if (!file) {
rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr);
@@ -5373,28 +5378,20 @@ rb_f_require(obj, fname)
}
buf = ALLOCA_N(char, strlen(RSTRING(fname)->ptr) + 5);
strcpy(buf, RSTRING(fname)->ptr);
- strcat(buf, ".rb");
- if (rb_find_file(buf)) {
+ switch (rb_find_file_noext(buf)) {
+ case 0:
+ break;
+
+ case 1:
fname = rb_str_new2(buf);
- feature = buf;
+ file = feature = buf;
goto load_rb;
- }
- strcpy(buf, RSTRING(fname)->ptr);
- strcat(buf, DLEXT);
- file = rb_find_file(buf);
- if (file) {
- feature = buf;
- goto load_dyna;
- }
-#ifdef DLEXT2
- strcpy(buf, RSTRING(fname)->ptr);
- strcat(buf, DLEXT2);
- file = rb_find_file(buf);
- if (file) {
+
+ default:
feature = buf;
+ file = rb_find_file(buf);
goto load_dyna;
}
-#endif
rb_raise(rb_eLoadError, "No such file to load -- %s",
RSTRING(fname)->ptr);
@@ -8145,6 +8142,11 @@ rb_thread_start_0(fn, arg, th_arg)
}
#endif
+ FL_SET(ruby_scope, SCOPE_SHARED);
+ if (THREAD_SAVE_CONTEXT(curr_thread)) {
+ return thread;
+ }
+
if (ruby_block) { /* should nail down higher scopes */
struct BLOCK dummy;
@@ -8153,10 +8155,6 @@ rb_thread_start_0(fn, arg, th_arg)
saved_block = ruby_block = dummy.prev;
}
scope_dup(ruby_scope);
- FL_SET(ruby_scope, SCOPE_SHARED);
- if (THREAD_SAVE_CONTEXT(curr_thread)) {
- return thread;
- }
if (!th->next) {
/* merge in thread list */
diff --git a/file.c b/file.c
index b246762a8c..b4e8ff138c 100644
--- a/file.c
+++ b/file.c
@@ -2124,40 +2124,100 @@ is_macos_native_path(path)
}
#endif
+static char*
+file_load_ok(file)
+ char *file;
+{
+ FILE *f;
+
+ f = fopen(file, "r");
+ if (f == NULL) return 0;
+ fclose(f);
+ return file;
+}
+
+extern VALUE rb_load_path;
+
+int
+rb_find_file_noext(file)
+ char *file;
+{
+ char *path, *e, *found;
+ char *fend = file + strlen(file);
+ VALUE fname;
+ int i, j;
+
+ static char *ext[] = {
+ ".rb", DLEXT,
+#ifdef DLEXT2
+ DLEXT2,
+#endif
+ 0
+ };
+
+ if (file[0] == '~') {
+ fname = rb_str_new2(file);
+ fname = rb_file_s_expand_path(1, &fname);
+ file = STR2CSTR(fname);
+ }
+
+ if (is_absolute_path(file)) {
+ for (i=0; ext[i]; i++) {
+ strcpy(fend, ext[i]);
+ if (file_load_ok(file)) return i+1;
+ }
+ return 0;
+ }
+
+ if (!rb_load_path) return 0;
+
+ Check_Type(rb_load_path, T_ARRAY);
+ for (i=0;i<RARRAY(rb_load_path)->len;i++) {
+ VALUE str = RARRAY(rb_load_path)->ptr[i];
+
+ Check_SafeStr(str);
+ path = RSTRING(str)->ptr;
+ for (j=0; ext[j]; j++) {
+ strcpy(fend, ext[j]);
+ found = dln_find_file(file, path);
+ if (found && file_load_ok(found)) return j+1;
+ }
+ }
+ return 0;
+}
+
char*
rb_find_file(file)
char *file;
{
- extern VALUE rb_load_path;
volatile VALUE vpath;
VALUE fname;
char *path;
struct stat st;
+ if (file[0] == '~') {
+ fname = rb_str_new2(file);
+ fname = rb_file_s_expand_path(1, &fname);
+ if (rb_safe_level() >= 2 && OBJ_TAINTED(fname)) {
+ rb_raise(rb_eSecurityError, "loading from unsafe file %s", file);
+ }
+ file = STR2CSTR(fname);
+ }
+
#if defined(__MACOS__) || defined(riscos)
if (is_macos_native_path(file)) {
- FILE *f;
-
if (rb_safe_level() >= 2 && !rb_path_check(file)) {
rb_raise(rb_eSecurityError, "loading from unsafe file %s", file);
}
- f= fopen(file, "r");
- if (f == NULL) return 0;
- fclose(f);
- return file;
+ return file_load_ok(file);
}
#endif
if (is_absolute_path(file)) {
- FILE *f;
-
if (rb_safe_level() >= 2 && !rb_path_check(file)) {
rb_raise(rb_eSecurityError, "loading from unsafe file %s", file);
}
- f = fopen(file, "r");
- if (f == NULL) return 0;
- fclose(f);
- return file;
+ return file_load_ok(file);
}
if (file[0] == '~') {
@@ -2192,10 +2252,7 @@ rb_find_file(file)
}
path = dln_find_file(file, path);
- if (path && stat(path, &st) == 0) {
- return path;
- }
- return 0;
+ return file_load_ok(path);
}
static void
diff --git a/io.c b/io.c
index 35c043b676..a950c9e634 100644
--- a/io.c
+++ b/io.c
@@ -3346,12 +3346,17 @@ static void
opt_i_set(val)
VALUE val;
{
- if (ruby_inplace_mode) free(ruby_inplace_mode);
+ long len;
+
if (!RTEST(val)) {
+ if (ruby_inplace_mode) free(ruby_inplace_mode);
ruby_inplace_mode = 0;
return;
}
- ruby_inplace_mode = strdup(STR2CSTR(val));
+ STR2CSTR(val);
+ len = RSTRING(val)->len;
+ REALLOC_N(ruby_inplace_mode, char, len + 1);
+ ((char *)MEMCPY(ruby_inplace_mode, RSTRING(val)->ptr, char, len))[len] = '\0';
}
void
diff --git a/regex.c b/regex.c
index 9033e0ac81..bc63fac651 100644
--- a/regex.c
+++ b/regex.c
@@ -1260,7 +1260,6 @@ re_compile_pattern(pattern, size, bufp)
int had_char_class = 0;
int options = bufp->options;
- int old_options = 0;
bufp->fastmap_accurate = 0;
bufp->must = 0;
@@ -1683,11 +1682,15 @@ re_compile_pattern(pattern, size, bufp)
break;
case '(':
- old_options = options;
+ {
+ int old_options = options;
+ int push_option = 0;
+ int casefold = 0;
+
PATFETCH(c);
if (c == '?') {
int negative = 0;
- int push_option = 0;
+
PATFETCH_RAW(c);
switch (c) {
case 'x': case 'p': case 'm': case 'i': case '-':
@@ -1736,13 +1739,12 @@ re_compile_pattern(pattern, size, bufp)
if (negative) {
if (options&RE_OPTION_IGNORECASE) {
options &= ~RE_OPTION_IGNORECASE;
- BUFPUSH(casefold_off);
}
}
else if (!(options&RE_OPTION_IGNORECASE)) {
options |= RE_OPTION_IGNORECASE;
- BUFPUSH(casefold_on);
}
+ casefold = 1;
break;
default:
@@ -1774,16 +1776,24 @@ re_compile_pattern(pattern, size, bufp)
default:
FREE_AND_RETURN(stackb, "undefined (?...) sequence");
}
+ }
+ else {
+ PATUNFETCH;
+ c = '(';
+ }
+ if (c == '#') {
if (push_option) {
BUFPUSH(option_set);
BUFPUSH(options);
}
+ if (casefold) {
+ if (options & RE_OPTION_IGNORECASE)
+ BUFPUSH(casefold_on);
+ else
+ BUFPUSH(casefold_off);
}
- else {
- PATUNFETCH;
- c = '(';
+ break;
}
- if (c == '#') break;
if (stackp+8 >= stacke) {
DOUBLE_STACK(int);
}
@@ -1826,24 +1836,28 @@ re_compile_pattern(pattern, size, bufp)
default:
break;
}
+ if (push_option) {
+ BUFPUSH(option_set);
+ BUFPUSH(options);
+ }
+ if (casefold) {
+ if (options & RE_OPTION_IGNORECASE)
+ BUFPUSH(casefold_on);
+ else
+ BUFPUSH(casefold_off);
+ }
*stackp++ = c;
*stackp++ = old_options;
fixup_alt_jump = 0;
laststart = 0;
begalt = b;
+ }
break;
case ')':
if (stackp == stackb)
FREE_AND_RETURN(stackb, "unmatched )");
- if (options != stackp[-1]) {
- if ((options ^ stackp[-1]) & RE_OPTION_IGNORECASE) {
- BUFPUSH((options&RE_OPTION_IGNORECASE)?casefold_off:casefold_on);
- }
- BUFPUSH(option_set);
- BUFPUSH(stackp[-1]);
- }
pending_exact = 0;
if (fixup_alt_jump) {
/* Push a dummy failure point at the end of the
@@ -1856,6 +1870,15 @@ re_compile_pattern(pattern, size, bufp)
to `fixup_alt_jump', in the `handle_alt' case below. */
store_jump(fixup_alt_jump, jump, b);
}
+ if (options != stackp[-1]) {
+ if ((options ^ stackp[-1]) & RE_OPTION_IGNORECASE) {
+ BUFPUSH((options&RE_OPTION_IGNORECASE)?casefold_off:casefold_on);
+ }
+ if ((options ^ stackp[-1]) != RE_OPTION_IGNORECASE) {
+ BUFPUSH(option_set);
+ BUFPUSH(stackp[-1]);
+ }
+ }
p0 = b;
options = *--stackp;
switch (c = *--stackp) {
@@ -3241,7 +3264,8 @@ re_search(bufp, string, size, startpos, range, regs)
}
if (startpos > size) return -1;
- if (anchor && size > 0 && startpos == size) return -1;
+ if ((anchor || !bufp->can_be_null) && size > 0 && startpos == size)
+ return -1;
val = re_match(bufp, string, size, startpos, regs);
if (val >= 0) return startpos;
if (val == -2) return -2;