1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* process.c (security): always give warning for insecure PATH.

* dir.c (my_getcwd): do not rely on MAXPATHLEN.

* file.c (rb_file_s_readlink): ditto.

* file.c (path_check_1): ditto.

* eval.c (rb_yield_0): should not call rb_f_block_given_p().

* string.c (rb_str_chomp_bang): should terminate string by NUL.

* eval.c (rb_yield_0): better error message.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1816 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2001-11-08 06:43:14 +00:00
parent ab827130d3
commit dc98adf839
17 changed files with 201 additions and 109 deletions

View file

@ -249,7 +249,7 @@ dmyext.@OBJEXT@: dmyext.c
enum.@OBJEXT@: enum.c ruby.h config.h defines.h intern.h node.h enum.@OBJEXT@: enum.c ruby.h config.h defines.h intern.h node.h
error.@OBJEXT@: error.c ruby.h config.h defines.h intern.h env.h version.h error.@OBJEXT@: error.c ruby.h config.h defines.h intern.h env.h version.h
eval.@OBJEXT@: eval.c ruby.h config.h defines.h intern.h node.h env.h rubysig.h st.h dln.h eval.@OBJEXT@: eval.c ruby.h config.h defines.h intern.h node.h env.h rubysig.h st.h dln.h
file.@OBJEXT@: file.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h dln.h file.@OBJEXT@: file.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h dln.h util.h
gc.@OBJEXT@: gc.c ruby.h config.h defines.h intern.h rubysig.h st.h node.h env.h re.h regex.h gc.@OBJEXT@: gc.c ruby.h config.h defines.h intern.h rubysig.h st.h node.h env.h re.h regex.h
hash.@OBJEXT@: hash.c ruby.h config.h defines.h intern.h st.h rubysig.h util.h hash.@OBJEXT@: hash.c ruby.h config.h defines.h intern.h st.h rubysig.h util.h
inits.@OBJEXT@: inits.c ruby.h config.h defines.h intern.h inits.@OBJEXT@: inits.c ruby.h config.h defines.h intern.h

View file

@ -609,6 +609,17 @@ rb_big_eq(x, y)
return Qtrue; return Qtrue;
} }
static VALUE
rb_big_eql(x, y)
VALUE x, y;
{
if (TYPE(y) != T_BIGNUM) return Qfalse;
if (RBIGNUM(x)->sign != RBIGNUM(y)->sign) return Qfalse;
if (RBIGNUM(x)->len != RBIGNUM(y)->len) return Qfalse;
if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM(y)->len) != 0) return Qfalse;
return Qtrue;
}
static VALUE static VALUE
rb_big_uminus(x) rb_big_uminus(x)
VALUE x; VALUE x;
@ -1454,7 +1465,7 @@ Init_Bignum()
rb_define_method(rb_cBignum, "<=>", rb_big_cmp, 1); rb_define_method(rb_cBignum, "<=>", rb_big_cmp, 1);
rb_define_method(rb_cBignum, "==", rb_big_eq, 1); rb_define_method(rb_cBignum, "==", rb_big_eq, 1);
rb_define_method(rb_cBignum, "===", rb_big_eq, 1); rb_define_method(rb_cBignum, "===", rb_big_eq, 1);
rb_define_method(rb_cBignum, "eql?", rb_big_eq, 1); rb_define_method(rb_cBignum, "eql?", rb_big_eql, 1);
rb_define_method(rb_cBignum, "hash", rb_big_hash, 0); rb_define_method(rb_cBignum, "hash", rb_big_hash, 0);
rb_define_method(rb_cBignum, "to_f", rb_big_to_f, 0); rb_define_method(rb_cBignum, "to_f", rb_big_to_f, 0);
rb_define_method(rb_cBignum, "abs", rb_big_abs, 0); rb_define_method(rb_cBignum, "abs", rb_big_abs, 0);

View file

@ -293,7 +293,7 @@ AC_FUNC_MEMCMP
AC_REPLACE_FUNCS(dup2 memmove mkdir strcasecmp strncasecmp strerror strftime\ AC_REPLACE_FUNCS(dup2 memmove mkdir strcasecmp strncasecmp strerror strftime\
strchr strstr strtoul crypt flock vsnprintf\ strchr strstr strtoul crypt flock vsnprintf\
isinf isnan finite hypot) isinf isnan finite hypot)
AC_CHECK_FUNCS(fmod killpg drand48 random wait4 waitpid syscall getcwd chroot\ AC_CHECK_FUNCS(fmod killpg drand48 random wait4 waitpid syscall chroot\
truncate chsize times utimes fcntl lockf lstat symlink readlink\ truncate chsize times utimes fcntl lockf lstat symlink readlink\
setitimer setruid seteuid setreuid setresuid setproctitle\ setitimer setruid seteuid setreuid setresuid setproctitle\
setrgid setegid setregid setresgid pause lchown lchmod\ setrgid setegid setregid setresgid pause lchown lchmod\
@ -581,7 +581,7 @@ if test "$with_dln_a_out" != yes; then
LDFLAGS="-Wl,-E" LDFLAGS="-Wl,-E"
rb_cv_dlopen=yes;; rb_cv_dlopen=yes;;
solaris*) if test "$GCC" = yes; then solaris*) if test "$GCC" = yes; then
LDSHARED='$(CC) -Wl,-G' LDSHARED='$(CC) -Wl,-G -shared'
`$CC --print-prog-name=ld` -v 2>&1 | grep "GNU ld" > /dev/null && LDFLAGS="-Wl,-E" `$CC --print-prog-name=ld` -v 2>&1 | grep "GNU ld" > /dev/null && LDFLAGS="-Wl,-E"
else else
LDSHARED='ld -G' LDSHARED='ld -G'

22
dir.c
View file

@ -61,6 +61,8 @@ char *strchr _((char*,char));
#include <ctype.h> #include <ctype.h>
#include "util.h"
#ifndef HAVE_LSTAT #ifndef HAVE_LSTAT
#define lstat(path,st) stat(path,st) #define lstat(path,st) stat(path,st)
#endif #endif
@ -430,21 +432,16 @@ static VALUE chdir_thread = Qnil;
static VALUE static VALUE
chdir_restore(path) chdir_restore(path)
const char *path; char *path;
{ {
chdir_blocking--; chdir_blocking--;
if (chdir_blocking == 0) if (chdir_blocking == 0)
chdir_thread = Qnil; chdir_thread = Qnil;
dir_chdir(path); dir_chdir(path);
free(path);
return Qnil; return Qnil;
} }
#ifdef HAVE_GETCWD
#define GETCWD(path) if (getcwd(path, sizeof(path)) == 0) rb_sys_fail(path)
#else
#define GETCWD(path) if (getwd(path) == 0) rb_sys_fail(path)
#endif
static VALUE static VALUE
dir_s_chdir(argc, argv, obj) dir_s_chdir(argc, argv, obj)
int argc; int argc;
@ -473,9 +470,7 @@ dir_s_chdir(argc, argv, obj)
} }
if (rb_block_given_p()) { if (rb_block_given_p()) {
char cwd[MAXPATHLEN]; char *cwd = my_getcwd();
GETCWD(cwd);
chdir_blocking++; chdir_blocking++;
if (chdir_thread == Qnil) if (chdir_thread == Qnil)
chdir_thread = rb_thread_current(); chdir_thread = rb_thread_current();
@ -491,10 +486,11 @@ static VALUE
dir_s_getwd(dir) dir_s_getwd(dir)
VALUE dir; VALUE dir;
{ {
char path[MAXPATHLEN]; char *path = my_getcwd();
VALUE cwd = rb_tainted_str_new2(path);
GETCWD(path); free(path);
return rb_tainted_str_new2(path); return cwd;
} }
static VALUE static VALUE

View file

@ -1,3 +1,36 @@
: String#chomp
if $/ == '\n', chops off last newlines (any of \n, \r, \r\n).
: IO#puts
do not treat Array specially.
: Module::new/Class::new
takes block.
: allocation framework
any instance of class can be allocated by class.allocate,
(except a few classes).
: String#[]
starting offset can be specified as optional second parameter.
: String/Array methods
returns an instance of receivers class.
: String::new
returns "".
: Dir#path
Added.
: Enum#sort_by : Enum#sort_by
Added. Added.

4
eval.c
View file

@ -3645,8 +3645,8 @@ rb_yield_0(val, self, klass, pcall)
int state; int state;
static unsigned serial = 1; static unsigned serial = 1;
if (!(rb_block_given_p() || rb_f_block_given_p())) { if (!rb_block_given_p()) {
rb_raise(rb_eLocalJumpError, "yield called out of block"); rb_raise(rb_eLocalJumpError, "no block given");
} }
PUSH_VARS(); PUSH_VARS();

76
file.c
View file

@ -19,6 +19,7 @@
#include "ruby.h" #include "ruby.h"
#include "rubyio.h" #include "rubyio.h"
#include "rubysig.h" #include "rubysig.h"
#include "util.h"
#include "dln.h" #include "dln.h"
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
@ -1225,14 +1226,22 @@ rb_file_s_readlink(klass, path)
VALUE klass, path; VALUE klass, path;
{ {
#ifdef HAVE_READLINK #ifdef HAVE_READLINK
char buf[MAXPATHLEN]; char *buf;
int cc; int size = 100;
int rv;
VALUE v;
SafeStringValue(path); SafeStringValue(path);
if ((cc = readlink(RSTRING(path)->ptr, buf, MAXPATHLEN)) < 0) buf = xmalloc(size);
rb_sys_fail(RSTRING(path)->ptr); if ((rv = readlink(RSTRING(path)->ptr, buf, size)) == size) {
size *= 2;
buf = xrealloc(buf, size);
}
if (rv < 0) rb_sys_fail(RSTRING(path)->ptr);
v = rb_tainted_str_new(buf, rv);
free(buf);
return rb_tainted_str_new(buf, cc); return v;
#else #else
rb_notimplement(); rb_notimplement();
return Qnil; /* not reached */ return Qnil; /* not reached */
@ -1297,10 +1306,6 @@ rb_file_s_umask(argc, argv)
return INT2FIX(omask); return INT2FIX(omask);
} }
#ifndef HAVE_GETCWD
#define getcwd(buf, len) ((void)(len), getwd(buf))
#endif
#if defined DOSISH #if defined DOSISH
#define isdirsep(x) ((x) == '/' || (x) == '\\') #define isdirsep(x) ((x) == '/' || (x) == '\\')
#else #else
@ -2228,29 +2233,31 @@ is_absolute_path(path)
static int static int
path_check_1(path) path_check_1(path)
char *path; VALUE path;
{ {
struct stat st; struct stat st;
char *p = 0; char *p0 = RSTRING(path)->ptr;
char *s; char *p, *s;
if (!is_absolute_path(path)) { if (!is_absolute_path(p0)) {
char buf[MAXPATHLEN+1]; char *buf = my_getcwd();
VALUE newpath;
if (getcwd(buf, MAXPATHLEN) == 0) return 0; newpath = rb_str_new2(buf);
strncat(buf, "/", MAXPATHLEN); free(buf);
strncat(buf, path, MAXPATHLEN);
buf[MAXPATHLEN] = '\0'; rb_str_cat2(newpath, "/");
return path_check_1(buf); rb_str_cat2(newpath, p0);
return path_check_1(newpath);
} }
for (;;) { for (;;) {
if (stat(path, &st) == 0 && (st.st_mode & 002)) { if (stat(p0, &st) == 0 && (st.st_mode & 002)) {
if (p) *p = '/'; if (p) *p = '/';
return 0; return 0;
} }
s = strrdirsep(path); s = strrdirsep(p0);
if (p) *p = '/'; if (p) *p = '/';
if (!s || s == path) return 1; if (!s || s == p0) return 1;
p = s; p = s;
*p = '\0'; *p = '\0';
} }
@ -2260,27 +2267,24 @@ int
rb_path_check(path) rb_path_check(path)
char *path; char *path;
{ {
char *p, *pend; char *p0, *p, *pend;
const char sep = PATH_SEP_CHAR; const char sep = PATH_SEP_CHAR;
if (!path) return 1; if (!path) return 1;
p = path; pend = path + strlen(path);
pend = strchr(path, sep); p0 = path;
p = strchr(path, sep);
if (!p) p = pend;
for (;;) { for (;;) {
int safe; if (!path_check_1(rb_str_new(p0, p - p0))) {
return 0; /* not safe */
if (pend) *pend = '\0';
safe = path_check_1(p);
if (!safe) {
if (pend) *pend = sep;
return 0;
} }
if (!pend) break; if (p0 > pend) break;
*pend = sep; p0 = p + 1;
p = pend + 1; p = strchr(p0, sep);
pend = strchr(p, sep); if (!p) p = pend;
} }
return 1; return 1;
} }

View file

@ -76,7 +76,7 @@ DNS stub resolver.
--- Resolv::DNS#getresource(name, typeclass) --- Resolv::DNS#getresource(name, typeclass)
--- Resolv::DNS#getresources(name, typeclass) --- Resolv::DNS#getresources(name, typeclass)
--- Resolv::DNS#each_resources(name, typeclass) {|resource| ...} --- Resolv::DNS#each_resource(name, typeclass) {|resource| ...}
They lookup DNS resources of ((|name|)). They lookup DNS resources of ((|name|)).
((|name|)) must be a instance of Resolv::Name or String. ((|name|)) must be a instance of Resolv::Name or String.
@ -370,7 +370,7 @@ class Resolv
end end
def each_address(name) def each_address(name)
each_resources(name, Resource::IN::A) {|resource| yield resource.address} each_resource(name, Resource::IN::A) {|resource| yield resource.address}
end end
def getname(address) def getname(address)
@ -395,21 +395,21 @@ class Resolv
else else
raise ResolvError.new("cannot interpret as address: #{address}") raise ResolvError.new("cannot interpret as address: #{address}")
end end
each_resources(ptr, Resource::IN::PTR) {|resource| yield resource.name} each_resource(ptr, Resource::IN::PTR) {|resource| yield resource.name}
end end
def getresource(name, typeclass) def getresource(name, typeclass)
each_resources(name, typeclass) {|resource| return resource} each_resource(name, typeclass) {|resource| return resource}
raise ResolvError.new("DNS result has no information for #{name}") raise ResolvError.new("DNS result has no information for #{name}")
end end
def getresources(name, typeclass) def getresources(name, typeclass)
ret = [] ret = []
each_resources(name, typeclass) {|resource| ret << resource} each_resource(name, typeclass) {|resource| ret << resource}
return ret return ret
end end
def each_resources(name, typeclass, &proc) def each_resource(name, typeclass, &proc)
lazy_initialize lazy_initialize
q = Queue.new q = Queue.new
senders = {} senders = {}
@ -1594,7 +1594,7 @@ class Resolv
def initialize(address) def initialize(address)
unless address.kind_of?(String) && address.length == 16 unless address.kind_of?(String) && address.length == 16
raise ArgumentError.new('IPv4 address muse be 16 bytes') raise ArgumentError.new('IPv6 address muse be 16 bytes')
end end
@address = address @address = address
end end

View file

@ -60,7 +60,11 @@ class WeakRef<Delegator
unless ID_MAP[@__id] unless ID_MAP[@__id]
raise RefError, "Illegal Reference - probably recycled", caller(2) raise RefError, "Illegal Reference - probably recycled", caller(2)
end end
begin
ObjectSpace._id2ref(@__id) ObjectSpace._id2ref(@__id)
rescue RangeError
raise RefError, "Illegal Reference - probably recycled", caller(2)
end
end end
def weakref_alive? def weakref_alive?

10
parse.y
View file

@ -428,6 +428,7 @@ stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem
| variable tOP_ASGN command_call | variable tOP_ASGN command_call
{ {
NODE *n = assignable($1, 0); NODE *n = assignable($1, 0);
if (n) {
if ($2 == tOROP) { if ($2 == tOROP) {
n->nd_value = $3; n->nd_value = $3;
$$ = NEW_OP_ASGN_OR(gettable($1), n); $$ = NEW_OP_ASGN_OR(gettable($1), n);
@ -447,6 +448,10 @@ stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem
} }
fixpos($$, $3); fixpos($$, $3);
} }
else {
$$ = 0;
}
}
| primary '[' aref_args ']' tOP_ASGN command_call | primary '[' aref_args ']' tOP_ASGN command_call
{ {
NODE *tmp, *args = NEW_LIST($6); NODE *tmp, *args = NEW_LIST($6);
@ -770,6 +775,7 @@ arg : lhs '=' arg
| variable tOP_ASGN arg | variable tOP_ASGN arg
{ {
NODE *n = assignable($1, 0); NODE *n = assignable($1, 0);
if (n) {
if ($2 == tOROP) { if ($2 == tOROP) {
n->nd_value = $3; n->nd_value = $3;
$$ = NEW_OP_ASGN_OR(gettable($1), n); $$ = NEW_OP_ASGN_OR(gettable($1), n);
@ -789,6 +795,10 @@ arg : lhs '=' arg
} }
fixpos($$, $3); fixpos($$, $3);
} }
else {
$$ = 0;
}
}
| primary '[' aref_args ']' tOP_ASGN arg | primary '[' aref_args ']' tOP_ASGN arg
{ {
NODE *tmp, *args = NEW_LIST($6); NODE *tmp, *args = NEW_LIST($6);

View file

@ -422,10 +422,13 @@ static void
security(str) security(str)
char *str; char *str;
{ {
if (rb_safe_level() > 0) {
if (rb_env_path_tainted()) { if (rb_env_path_tainted()) {
if (rb_safe_level() > 0) {
rb_raise(rb_eSecurityError, "Insecure PATH - %s", str); rb_raise(rb_eSecurityError, "Insecure PATH - %s", str);
} }
else {
rb_warn("Insecure PATH - %s", str);
}
} }
} }
@ -521,8 +524,6 @@ rb_proc_exec(str)
char *ss, *t; char *ss, *t;
char **argv, **a; char **argv, **a;
security(str);
while (*str && ISSPACE(*str)) while (*str && ISSPACE(*str))
str++; str++;

17
ruby.h
View file

@ -35,15 +35,16 @@ extern "C" {
#include <stdio.h> #include <stdio.h>
/* need to include <ctype.h> to use these macros */ /* need to include <ctype.h> to use these macros */
#define ISASCII(c) isascii((unsigned char)(c))
#undef ISPRINT #undef ISPRINT
#define ISPRINT(c) isprint((unsigned char)(c)) #define ISPRINT(c) (ISASCII(c) && isprint((unsigned char)(c)))
#define ISSPACE(c) isspace((unsigned char)(c)) #define ISSPACE(c) (ISASCII(c) && isspace((unsigned char)(c)))
#define ISUPPER(c) isupper((unsigned char)(c)) #define ISUPPER(c) (ISASCII(c) && isupper((unsigned char)(c)))
#define ISLOWER(c) islower((unsigned char)(c)) #define ISLOWER(c) (ISASCII(c) && islower((unsigned char)(c)))
#define ISALNUM(c) isalnum((unsigned char)(c)) #define ISALNUM(c) (ISASCII(c) && isalnum((unsigned char)(c)))
#define ISALPHA(c) isalpha((unsigned char)(c)) #define ISALPHA(c) (ISASCII(c) && isalpha((unsigned char)(c)))
#define ISDIGIT(c) isdigit((unsigned char)(c)) #define ISDIGIT(c) (ISASCII(c) && isdigit((unsigned char)(c)))
#define ISXDIGIT(c) isxdigit((unsigned char)(c)) #define ISXDIGIT(c) (ISASCII(c) && isxdigit((unsigned char)(c)))
#if !defined(__STDC__) && !defined(_MSC_VER) #if !defined(__STDC__) && !defined(_MSC_VER)
# define volatile # define volatile

View file

@ -1329,6 +1329,16 @@ begin
rescue rescue
test_ok false test_ok false
end end
class S
def initialize(a)
@a = a
end
end
l=nil
100000.times {
l = S.new(l)
}
test_ok true # reach here or dumps core
if $failed > 0 if $failed > 0
printf "test: %d failed %d\n", $ntest, $failed printf "test: %d failed %d\n", $ntest, $failed

View file

@ -291,6 +291,8 @@ rb_str_dup(str)
} }
else if (RSTRING(str)->orig) { else if (RSTRING(str)->orig) {
str2 = rb_str_new3(RSTRING(str)->orig); str2 = rb_str_new3(RSTRING(str)->orig);
FL_UNSET(str2, FL_TAINT);
OBJ_INFECT(str2, str);
} }
else { else {
str2 = rb_str_new3(rb_str_new4(str)); str2 = rb_str_new3(rb_str_new4(str));
@ -2673,14 +2675,16 @@ rb_str_chomp_bang(argc, argv, str)
RSTRING(str)->ptr[RSTRING(str)->len-1] == '\r') { RSTRING(str)->ptr[RSTRING(str)->len-1] == '\r') {
RSTRING(str)->len--; RSTRING(str)->len--;
} }
return str;
} }
else if (RSTRING(str)->ptr[len-1] == '\r') { else if (RSTRING(str)->ptr[len-1] == '\r') {
RSTRING(str)->len--; RSTRING(str)->len--;
return str;
} }
else {
return Qnil; return Qnil;
} }
RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
return str;
}
} }
if (NIL_P(rs)) return Qnil; if (NIL_P(rs)) return Qnil;
if (len == 0) return Qnil; if (len == 0) return Qnil;

15
util.c
View file

@ -11,6 +11,7 @@
**********************************************************************/ **********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#ifdef NT #ifdef NT
#include "missing/file.h" #include "missing/file.h"
@ -628,3 +629,17 @@ ruby_strdup(str)
return tmp; return tmp;
} }
char *
ruby_getcwd()
{
int size = 200;
char *buf = xmalloc(size);
while (!getcwd(buf, size)) {
if (errno != ERANGE) rb_sys_fail(buf);
size *= 2;
buf = xrealloc(buf, size);
}
return buf;
}

3
util.h
View file

@ -50,4 +50,7 @@ char *ruby_strdup _((const char*));
#undef strdup #undef strdup
#define strdup(s) ruby_strdup((s)) #define strdup(s) ruby_strdup((s))
char *ruby_getcwd _((void));
#define my_getcwd() ruby_getcwd()
#endif /* UTIL_H */ #endif /* UTIL_H */

View file

@ -1,4 +1,4 @@
#define RUBY_VERSION "1.7.2" #define RUBY_VERSION "1.7.2"
#define RUBY_RELEASE_DATE "2001-11-02" #define RUBY_RELEASE_DATE "2001-11-08"
#define RUBY_VERSION_CODE 172 #define RUBY_VERSION_CODE 172
#define RUBY_RELEASE_CODE 20011102 #define RUBY_RELEASE_CODE 20011108