Skip to content

Commit

Permalink
* dir.c (rb_glob2): do not allocate buffer from heap to avoid
Browse files Browse the repository at this point in the history
  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
  • Loading branch information
matz committed Nov 10, 2004
1 parent 63b9174 commit 683400f
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 86 deletions.
22 changes: 22 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ Tue Nov 9 00:50:06 2004 Dave Thomas <[email protected]>

* lib/rdoc/rdoc.rb: Change version numbering of RDoc and ri

Tue Nov 9 01:05:04 2004 Yukihiro Matsumoto <[email protected]>

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

* lib/drb/extservm.rb: add DRb::ExtServManager#uri=.
Expand Down Expand Up @@ -67,6 +80,11 @@ Sat Nov 6 11:18:59 2004 Tadayoshi Funaba <[email protected]>

* lib/date.rb (_parse): checks whether zone was given.

Sat Nov 6 00:46:27 2004 Yukihiro Matsumoto <[email protected]>

* string.c (rb_str_locktmp): check STR_TMPLOCK flag before
locking. [ruby-dev:24727]

Fri Nov 5 19:07:16 2004 NARUSE, Yui <[email protected]>

* ext/nkf: follow CVS Head of original nkf.
Expand All @@ -93,6 +111,10 @@ Fri Nov 5 13:17:54 2004 Hidetoshi NAGAI <[email protected]>

* ext/tk/lib/tk/text.rb: bug fix

Fri Nov 5 08:52:48 2004 Yukihiro Matsumoto <[email protected]>

* gc.c (gc_mark): stricter GC stack check.

Fri Nov 5 08:34:43 2004 Yukihiro Matsumoto <[email protected]>

* string.c (str_gsub): should have removed rb_str_unlocktmp(str).
Expand Down
151 changes: 85 additions & 66 deletions dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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] == '/') {
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
};

Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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;
Expand All @@ -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;
}

Expand All @@ -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);
Expand All @@ -1333,10 +1335,9 @@ glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
}

buf = join_path(path, dirsep, name);
free(name);
status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg, new_end, flags, func, arg);
free(buf);
free(new_beg);
free(name);
if (status) break;
}
}
Expand All @@ -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;

Expand All @@ -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;

Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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()) {
Expand Down
1 change: 1 addition & 0 deletions eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading

0 comments on commit 683400f

Please sign in to comment.