mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* dir.c (rb_glob2): do not allocate buffer from heap to avoid
memory leaks. use string object for buffering instead. [ruby-dev:24738] * dir.c (join_path): ditto. * io.c (io_read): external input buffer may be modified even after rb_str_locktmp(). [ruby-dev:24735] * dir.c (fnmatch): p or s may be NULL. [ruby-dev:24749] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7242 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
63b9174a64
commit
683400f427
9 changed files with 126 additions and 86 deletions
22
ChangeLog
22
ChangeLog
|
@ -25,6 +25,19 @@ Tue Nov 9 00:50:06 2004 Dave Thomas <dave@pragprog.com>
|
|||
|
||||
* lib/rdoc/rdoc.rb: Change version numbering of RDoc and ri
|
||||
|
||||
Tue Nov 9 01:05:04 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* dir.c (rb_glob2): do not allocate buffer from heap to avoid
|
||||
memory leaks. use string object for buffering instead.
|
||||
[ruby-dev:24738]
|
||||
|
||||
* dir.c (join_path): ditto.
|
||||
|
||||
* io.c (io_read): external input buffer may be modified even after
|
||||
rb_str_locktmp(). [ruby-dev:24735]
|
||||
|
||||
* dir.c (fnmatch): p or s may be NULL. [ruby-dev:24749]
|
||||
|
||||
Tue Nov 9 00:36:26 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
|
||||
|
||||
* lib/drb/extservm.rb: add DRb::ExtServManager#uri=.
|
||||
|
@ -67,6 +80,11 @@ Sat Nov 6 11:18:59 2004 Tadayoshi Funaba <tadf@dotrb.org>
|
|||
|
||||
* lib/date.rb (_parse): checks whether zone was given.
|
||||
|
||||
Sat Nov 6 00:46:27 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* string.c (rb_str_locktmp): check STR_TMPLOCK flag before
|
||||
locking. [ruby-dev:24727]
|
||||
|
||||
Fri Nov 5 19:07:16 2004 NARUSE, Yui <naruse@ruby-lang.org>
|
||||
|
||||
* ext/nkf: follow CVS Head of original nkf.
|
||||
|
@ -93,6 +111,10 @@ Fri Nov 5 13:17:54 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
|
|||
|
||||
* ext/tk/lib/tk/text.rb: bug fix
|
||||
|
||||
Fri Nov 5 08:52:48 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* gc.c (gc_mark): stricter GC stack check.
|
||||
|
||||
Fri Nov 5 08:34:43 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* string.c (str_gsub): should have removed rb_str_unlocktmp(str).
|
||||
|
|
151
dir.c
151
dir.c
|
@ -303,6 +303,8 @@ fnmatch(p, s, flags)
|
|||
const char *ptmp = 0;
|
||||
const char *stmp = 0;
|
||||
|
||||
if (!p) p = "";
|
||||
if (!s) s = "";
|
||||
if (pathname) {
|
||||
while (1) {
|
||||
if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
|
||||
|
@ -1120,22 +1122,21 @@ glob_free_pattern(list)
|
|||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
static VALUE
|
||||
join_path(path, dirsep, name)
|
||||
const char *path;
|
||||
VALUE path;
|
||||
int dirsep;
|
||||
const char *name;
|
||||
{
|
||||
const int len = strlen(path);
|
||||
char *buf = ALLOC_N(char, len+1+strlen(name)+1);
|
||||
strcpy(buf, path);
|
||||
long len = RSTRING(path)->len;
|
||||
VALUE buf = rb_str_new(0, RSTRING(path)->len+strlen(name)+(dirsep?1:0));
|
||||
|
||||
memcpy(RSTRING(buf)->ptr, RSTRING(path)->ptr, len);
|
||||
if (dirsep) {
|
||||
strcpy(buf+len, "/");
|
||||
strcpy(buf+len+1, name);
|
||||
}
|
||||
else {
|
||||
strcpy(buf+len, name);
|
||||
strcpy(RSTRING(buf)->ptr+len, "/");
|
||||
len++;
|
||||
}
|
||||
strcpy(RSTRING(buf)->ptr+len, name);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -1154,8 +1155,8 @@ enum answer { YES, NO, UNKNOWN };
|
|||
#endif
|
||||
|
||||
struct glob_args {
|
||||
void (*func) _((const char*, VALUE));
|
||||
const char *c;
|
||||
void (*func) _((VALUE, VALUE));
|
||||
VALUE c;
|
||||
VALUE v;
|
||||
};
|
||||
|
||||
|
@ -1166,14 +1167,17 @@ glob_func_caller(val)
|
|||
VALUE val;
|
||||
{
|
||||
struct glob_args *args = (struct glob_args *)val;
|
||||
(*args->func)(args->c, args->v);
|
||||
VALUE path = args->c;
|
||||
|
||||
OBJ_TAINT(path);
|
||||
(*args->func)(path, args->v);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static int
|
||||
glob_call_func(func, path, arg)
|
||||
void (*func) _((const char*, VALUE));
|
||||
const char *path;
|
||||
void (*func) _((VALUE, VALUE));
|
||||
VALUE path;
|
||||
VALUE arg;
|
||||
{
|
||||
int status;
|
||||
|
@ -1189,14 +1193,14 @@ glob_call_func(func, path, arg)
|
|||
|
||||
static int
|
||||
glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
|
||||
const char *path;
|
||||
VALUE path;
|
||||
int dirsep; /* '/' should be placed before appending child entry's name to 'path'. */
|
||||
enum answer exist; /* Does 'path' indicate an existing entry? */
|
||||
enum answer isdir; /* Does 'path' indicate a directory or a symlink to a directory? */
|
||||
struct glob_pattern **beg;
|
||||
struct glob_pattern **end;
|
||||
int flags;
|
||||
void (*func) _((const char*, VALUE));
|
||||
void (*func) _((VALUE, VALUE));
|
||||
VALUE arg;
|
||||
{
|
||||
struct stat st;
|
||||
|
@ -1227,7 +1231,7 @@ glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
|
|||
}
|
||||
}
|
||||
|
||||
if (*path) {
|
||||
if (RSTRING(path)->len > 0) {
|
||||
if (match_all && exist == UNKNOWN) {
|
||||
if (do_lstat(path, &st) == 0) {
|
||||
exist = YES;
|
||||
|
@ -1256,9 +1260,7 @@ glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
|
|||
}
|
||||
|
||||
if (match_dir && isdir == YES) {
|
||||
char *buf = join_path(path, dirsep, "");
|
||||
status = glob_call_func(func, buf, arg);
|
||||
free(buf);
|
||||
status = glob_call_func(func, join_path(path, dirsep, ""), arg);
|
||||
if (status) return status;
|
||||
}
|
||||
}
|
||||
|
@ -1267,17 +1269,17 @@ glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
|
|||
|
||||
if (magical || recursive) {
|
||||
struct dirent *dp;
|
||||
DIR *dirp = do_opendir(*path ? path : ".");
|
||||
DIR *dirp = do_opendir(RSTRING(path)->len > 0 ? RSTRING(path)->ptr : ".");
|
||||
if (dirp == NULL) return 0;
|
||||
|
||||
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
|
||||
char *buf = join_path(path, dirsep, dp->d_name);
|
||||
VALUE buf = join_path(path, dirsep, dp->d_name);
|
||||
|
||||
enum answer new_isdir = UNKNOWN;
|
||||
if (recursive && strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0
|
||||
&& fnmatch("*", dp->d_name, flags) == 0) {
|
||||
#ifndef _WIN32
|
||||
if (do_lstat(buf, &st) == 0)
|
||||
if (do_lstat(RSTRING(buf)->ptr, &st) == 0)
|
||||
new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
|
||||
else
|
||||
new_isdir = NO;
|
||||
|
@ -1303,7 +1305,6 @@ glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
|
|||
|
||||
status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end, flags, func, arg);
|
||||
free(new_beg);
|
||||
free(buf);
|
||||
if (status) break;
|
||||
}
|
||||
|
||||
|
@ -1318,7 +1319,8 @@ glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
|
|||
|
||||
for (cur = copy_beg; cur < copy_end; ++cur) {
|
||||
if (*cur) {
|
||||
char *name, *buf;
|
||||
VALUE buf;
|
||||
char *name;
|
||||
name = ALLOC_N(char, strlen((*cur)->str) + 1);
|
||||
strcpy(name, (*cur)->str);
|
||||
if (escape) remove_backslashes(name);
|
||||
|
@ -1333,10 +1335,9 @@ glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
|
|||
}
|
||||
|
||||
buf = join_path(path, dirsep, name);
|
||||
status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg, new_end, flags, func, arg);
|
||||
free(buf);
|
||||
free(new_beg);
|
||||
free(name);
|
||||
status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg, new_end, flags, func, arg);
|
||||
free(new_beg);
|
||||
if (status) break;
|
||||
}
|
||||
}
|
||||
|
@ -1349,14 +1350,14 @@ glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
|
|||
|
||||
static int
|
||||
rb_glob2(path, flags, func, arg)
|
||||
const char *path;
|
||||
VALUE path;
|
||||
int flags;
|
||||
void (*func) _((const char*, VALUE));
|
||||
void (*func) _((VALUE, VALUE));
|
||||
VALUE arg;
|
||||
{
|
||||
struct glob_pattern *list;
|
||||
const char *root = path;
|
||||
char *buf;
|
||||
const char *root;
|
||||
VALUE buf;
|
||||
int n;
|
||||
int status;
|
||||
|
||||
|
@ -1366,55 +1367,75 @@ rb_glob2(path, flags, func, arg)
|
|||
|
||||
#if defined DOSISH
|
||||
flags |= FNM_CASEFOLD;
|
||||
root = rb_path_skip_prefix(root);
|
||||
root = rb_path_skip_prefix(RSTRING(path)->ptr);
|
||||
#else
|
||||
root = StringValuePtr(path);
|
||||
flags &= ~FNM_CASEFOLD;
|
||||
#endif
|
||||
|
||||
if (*root == '/') root++;
|
||||
if (root && *root == '/') root++;
|
||||
|
||||
n = root - path;
|
||||
buf = ALLOC_N(char, n+1);
|
||||
memcpy(buf, path, n);
|
||||
buf[n] = '\0';
|
||||
n = root - RSTRING(path)->ptr;
|
||||
buf = rb_str_new(RSTRING(path)->ptr, n);
|
||||
|
||||
list = glob_make_pattern(root, flags);
|
||||
status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg);
|
||||
glob_free_pattern(list);
|
||||
|
||||
free(buf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
struct rb_glob_args {
|
||||
void (*func) _((const char*, VALUE));
|
||||
VALUE arg;
|
||||
};
|
||||
|
||||
static VALUE
|
||||
rb_glob_caller(path, a)
|
||||
VALUE path, a;
|
||||
{
|
||||
struct rb_glob_args *args = (struct rb_glob_args *)a;
|
||||
(*args->func)(RSTRING(path)->ptr, args->arg);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
void
|
||||
rb_glob(path, func, arg)
|
||||
const char *path;
|
||||
void (*func) _((const char*, VALUE));
|
||||
VALUE arg;
|
||||
{
|
||||
int status = rb_glob2(path, 0, func, arg);
|
||||
struct rb_glob_args args;
|
||||
int status;
|
||||
|
||||
args.func = func;
|
||||
args.arg = arg;
|
||||
status = rb_glob2(rb_str_new2(path), 0, func, &args);
|
||||
|
||||
if (status) rb_jump_tag(status);
|
||||
}
|
||||
|
||||
static void
|
||||
push_pattern(path, ary)
|
||||
const char *path;
|
||||
VALUE ary;
|
||||
VALUE path, ary;
|
||||
{
|
||||
rb_ary_push(ary, rb_tainted_str_new2(path));
|
||||
rb_ary_push(ary, path);
|
||||
}
|
||||
|
||||
static int
|
||||
push_glob(ary, s, flags)
|
||||
push_glob(VALUE ary, VALUE s, long offset, int flags);
|
||||
|
||||
static int
|
||||
push_glob(ary, str, offset, flags)
|
||||
VALUE ary;
|
||||
const char *s;
|
||||
VALUE str;
|
||||
long offset;
|
||||
int flags;
|
||||
{
|
||||
const int escape = !(flags & FNM_NOESCAPE);
|
||||
|
||||
const char *p = s;
|
||||
const char *p = RSTRING(str)->ptr + offset;
|
||||
const char *s = RSTRING(str)->ptr + offset;
|
||||
const char *lbrace = 0, *rbrace = 0;
|
||||
int nest = 0, status = 0;
|
||||
|
||||
|
@ -1433,10 +1454,13 @@ push_glob(ary, s, flags)
|
|||
}
|
||||
|
||||
if (lbrace && rbrace) {
|
||||
char *buf, *b;
|
||||
buf = xmalloc(strlen(s) + 1);
|
||||
VALUE buffer = rb_str_new(0, strlen(s));
|
||||
char *buf;
|
||||
long offset;
|
||||
|
||||
buf = RSTRING(buffer)->ptr;
|
||||
memcpy(buf, s, lbrace-s);
|
||||
b = buf + (lbrace-s);
|
||||
offset = (lbrace-s);
|
||||
p = lbrace;
|
||||
while (p < rbrace) {
|
||||
const char *t = ++p;
|
||||
|
@ -1449,15 +1473,14 @@ push_glob(ary, s, flags)
|
|||
}
|
||||
Inc(p);
|
||||
}
|
||||
memcpy(b, t, p-t);
|
||||
strcpy(b+(p-t), rbrace+1);
|
||||
status = push_glob(ary, buf, flags);
|
||||
memcpy(buf+offset, t, p-t);
|
||||
strcpy(buf+offset+(p-t), rbrace+1);
|
||||
status = push_glob(ary, buffer, offset, flags);
|
||||
if (status) break;
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
else if (!lbrace && !rbrace) {
|
||||
status = rb_glob2(s, flags, push_pattern, ary);
|
||||
status = rb_glob2(str, flags, push_pattern, ary);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -1468,22 +1491,18 @@ rb_push_glob(str, flags) /* '\0' is delimiter */
|
|||
VALUE str;
|
||||
int flags;
|
||||
{
|
||||
const char *p, *pend;
|
||||
long offset = 0;
|
||||
VALUE ary;
|
||||
|
||||
FilePathValue(str);
|
||||
|
||||
ary = rb_ary_new();
|
||||
p = RSTRING(str)->ptr;
|
||||
pend = p + RSTRING(str)->len;
|
||||
|
||||
while (p < pend) {
|
||||
if (*p) {
|
||||
int status = push_glob(ary, p, flags);
|
||||
if (status) rb_jump_tag(status);
|
||||
p += strlen(p);
|
||||
}
|
||||
else p++;
|
||||
while (offset < RSTRING(str)->len) {
|
||||
int status = push_glob(ary, str, offset, flags);
|
||||
if (status) rb_jump_tag(status);
|
||||
offset += strlen(RSTRING(str)->ptr+offset) + 1;
|
||||
while (!RSTRING(str)->ptr[offset]) offset++;
|
||||
}
|
||||
|
||||
if (rb_block_given_p()) {
|
||||
|
|
1
eval.c
1
eval.c
|
@ -1393,6 +1393,7 @@ ruby_finalize_0()
|
|||
static void
|
||||
ruby_finalize_1()
|
||||
{
|
||||
signal(SIGINT, SIG_DFL);
|
||||
ruby_errinfo = 0;
|
||||
rb_gc_call_finalizer_at_exit();
|
||||
trace_func = 0;
|
||||
|
|
|
@ -476,9 +476,6 @@ s_recvfrom(sock, argc, argv, from)
|
|||
retry:
|
||||
rb_str_locktmp(str);
|
||||
rb_thread_wait_fd(fd);
|
||||
if (buflen != RSTRING(str)->len) {
|
||||
rb_raise(rb_eRuntimeError, "buffer modified");
|
||||
}
|
||||
TRAP_BEG;
|
||||
slen = recvfrom(fd, RSTRING(str)->ptr, buflen, flags, (struct sockaddr*)buf, &alen);
|
||||
TRAP_END;
|
||||
|
@ -1989,8 +1986,6 @@ sock_connect(sock, addr)
|
|||
int fd, n;
|
||||
|
||||
StringValue(addr);
|
||||
rb_str_modify(addr);
|
||||
|
||||
GetOpenFile(sock, fptr);
|
||||
fd = fileno(fptr->f);
|
||||
rb_str_locktmp(addr);
|
||||
|
@ -2010,8 +2005,6 @@ sock_bind(sock, addr)
|
|||
OpenFile *fptr;
|
||||
|
||||
StringValue(addr);
|
||||
rb_str_modify(addr);
|
||||
|
||||
GetOpenFile(sock, fptr);
|
||||
if (bind(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0)
|
||||
rb_sys_fail("bind(2)");
|
||||
|
|
2
gc.c
2
gc.c
|
@ -709,7 +709,7 @@ gc_mark(ptr, lev)
|
|||
if (obj->as.basic.flags & FL_MARK) return; /* already marked */
|
||||
obj->as.basic.flags |= FL_MARK;
|
||||
|
||||
if (lev > GC_LEVEL_MAX) {
|
||||
if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) {
|
||||
if (!mark_stack_overflow) {
|
||||
if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) {
|
||||
*mark_stack_ptr = ptr;
|
||||
|
|
5
io.c
5
io.c
|
@ -330,7 +330,9 @@ io_fflush(f, fptr)
|
|||
rb_io_check_closed(fptr);
|
||||
}
|
||||
for (;;) {
|
||||
TRAP_BEG;
|
||||
n = fflush(f);
|
||||
TRAP_END;
|
||||
if (n != EOF) break;
|
||||
if (!rb_io_wait_writable(fileno(f)))
|
||||
rb_sys_fail(fptr->path);
|
||||
|
@ -1216,6 +1218,9 @@ io_read(argc, argv, io)
|
|||
|
||||
rb_str_locktmp(str);
|
||||
READ_CHECK(fptr->f);
|
||||
if (RSTRING(str)->len != len) {
|
||||
rb_raise(rb_eRuntimeError, "buffer string modified");
|
||||
}
|
||||
n = rb_io_fread(RSTRING(str)->ptr, len, fptr->f);
|
||||
rb_str_unlocktmp(str);
|
||||
if (n == 0) {
|
||||
|
|
|
@ -41,8 +41,8 @@ module Shellwords
|
|||
snippet = $1
|
||||
elsif line =~ /\A'/ then
|
||||
raise ArgumentError, "Unmatched single quote: #{line}"
|
||||
elsif line.sub!(/\A\\(.)/, '') then
|
||||
snippet = $1
|
||||
elsif line.sub!(/\A\\(.)?/, '') then
|
||||
snippet = $1 || '\\'
|
||||
elsif line.sub!(/\A([^\s\\'"]+)/, '') then
|
||||
snippet = $1
|
||||
else
|
||||
|
|
4
pack.c
4
pack.c
|
@ -175,7 +175,7 @@ define_swapx(d, double)
|
|||
#endif /* #if SIZEOF_LONG == 8 */
|
||||
#else /* SIZEOF_DOUBLE != 8 */
|
||||
define_swapx(d, double)
|
||||
#endif /* #if SIZEOF_DPOUBLE == 8 */
|
||||
#endif /* #if SIZEOF_DOUBLE == 8 */
|
||||
|
||||
#undef define_swapx
|
||||
|
||||
|
@ -248,7 +248,7 @@ endian()
|
|||
#define hton32(x) (x)
|
||||
# endif
|
||||
#else /* LITTLE ENDIAN */
|
||||
#ifndef ntohs
|
||||
#ifdef ntohs
|
||||
#undef ntohs
|
||||
#undef ntohl
|
||||
#undef htons
|
||||
|
|
16
string.c
16
string.c
|
@ -252,13 +252,6 @@ rb_str_shared_replace(str, str2)
|
|||
if (str == str2) return;
|
||||
rb_str_modify(str);
|
||||
if (!FL_TEST(str, ELTS_SHARED)) free(RSTRING(str)->ptr);
|
||||
if (NIL_P(str2)) {
|
||||
RSTRING(str)->ptr = 0;
|
||||
RSTRING(str)->len = 0;
|
||||
RSTRING(str)->aux.capa = 0;
|
||||
FL_UNSET(str, STR_NOCAPA);
|
||||
return;
|
||||
}
|
||||
RSTRING(str)->ptr = RSTRING(str2)->ptr;
|
||||
RSTRING(str)->len = RSTRING(str2)->len;
|
||||
FL_UNSET(str, STR_NOCAPA);
|
||||
|
@ -640,6 +633,9 @@ VALUE
|
|||
rb_str_locktmp(str)
|
||||
VALUE str;
|
||||
{
|
||||
if (FL_TEST(str, STR_TMPLOCK)) {
|
||||
rb_raise(rb_eRuntimeError, "temporal locking already locked string");
|
||||
}
|
||||
FL_SET(str, STR_TMPLOCK);
|
||||
return str;
|
||||
}
|
||||
|
@ -648,6 +644,9 @@ VALUE
|
|||
rb_str_unlocktmp(str)
|
||||
VALUE str;
|
||||
{
|
||||
if (!FL_TEST(str, STR_TMPLOCK)) {
|
||||
rb_raise(rb_eRuntimeError, "temporal unlocking already unlocked string");
|
||||
}
|
||||
FL_UNSET(str, STR_TMPLOCK);
|
||||
return str;
|
||||
}
|
||||
|
@ -2278,7 +2277,8 @@ rb_str_clear(str)
|
|||
}
|
||||
RSTRING(str)->aux.shared = 0;
|
||||
FL_UNSET(str, STR_NOCAPA);
|
||||
RSTRING(str)->ptr = 0;
|
||||
FL_SET(str, ELTS_SHARED);
|
||||
RSTRING(str)->ptr = null_str;
|
||||
RARRAY(str)->len = 0;
|
||||
return str;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue