* dir.c (glob_helper): prevent memory leak using rb_protect().

* string.c (rb_str_associate): no need to check freeze flag.

* string.c (rb_str_resize): should honor STR_ASSOC flag on
  resize.

* string.c (rb_str_resize): proper STR_ASSOC handling.  pointed
  out by Michal Rokos.

* string.c (rb_str_buf_cat): ditto.

* string.c (rb_str_cat): ditto.

* string.c (rb_str_buf_append): ditto.

* string.c (rb_str_append): ditto.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2856 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2002-09-12 06:27:15 +00:00
parent e78e79e10f
commit b031fdbc0e
4 changed files with 157 additions and 82 deletions

View File

@ -66,6 +66,26 @@ Wed Sep 11 00:41:10 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* eval.c (rb_mod_define_method): initialize orig_func too.
(ruby-bugs-ja:PR#330)
Wed Sep 11 00:01:32 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
* dir.c (glob_helper): prevent memory leak using rb_protect().
* string.c (rb_str_associate): no need to check freeze flag.
* string.c (rb_str_resize): should honor STR_ASSOC flag on
resize.
* string.c (rb_str_resize): proper STR_ASSOC handling. pointed
out by Michal Rokos.
* string.c (rb_str_buf_cat): ditto.
* string.c (rb_str_cat): ditto.
* string.c (rb_str_buf_append): ditto.
* string.c (rb_str_append): ditto.
Tue Sep 10 23:35:46 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* parse.y (nextc): restore line number after here documents.

84
dir.c
View File

@ -653,7 +653,38 @@ remove_backslashes(p)
# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
#endif
static void
struct glob_args {
void (*func) _((const char*, VALUE));
const char *c;
VALUE v;
};
static VALUE
glob_func_caller(args)
struct glob_args *args;
{
(*args->func)(args->c, args->v);
return Qnil;
}
static int
glob_call_func(func, path, arg)
void (*func) _((const char*, VALUE));
const char *path;
VALUE arg;
{
int status;
struct glob_args args;
args.func = func;
args.c = path;
args.v = arg;
rb_protect(glob_func_caller, (VALUE)&args, &status);
return status;
}
static int
glob_helper(path, sub, flags, func, arg)
char *path;
char *sub;
@ -663,6 +694,7 @@ glob_helper(path, sub, flags, func, arg)
{
struct stat st;
char *p, *m;
int status = 0;
p = sub ? sub : path;
if (!has_magic(p, 0, flags)) {
@ -672,17 +704,18 @@ glob_helper(path, sub, flags, func, arg)
if (!(flags & FNM_NOESCAPE)) remove_backslashes(p);
#endif
if (lstat(path, &st) == 0) {
(*func)(path, arg);
status = glob_call_func(func, path, arg);
if (status) return status;
}
else if (errno != ENOENT) {
/* In case stat error is other than ENOENT and
we may want to know what is wrong. */
rb_sys_warning(path);
}
return;
return 0;
}
while (p) {
while (p && !status) {
if (*p == '/') p++;
m = strchr(p, '/');
if (has_magic(p, m, flags)) {
@ -704,6 +737,7 @@ glob_helper(path, sub, flags, func, arg)
if (stat(dir, &st) < 0) {
if (errno != ENOENT) rb_sys_warning(dir);
free(base);
free(magic);
break;
}
if (S_ISDIR(st.st_mode)) {
@ -712,18 +746,21 @@ glob_helper(path, sub, flags, func, arg)
recursive = 1;
buf = ALLOC_N(char, n+strlen(m)+3);
sprintf(buf, "%s%s", base, *base ? m : m+1);
glob_helper(buf, buf+n, flags, func, arg);
status = glob_helper(buf, buf+n, flags, func, arg);
free(buf);
if (status) goto finalize;
}
dirp = opendir(dir);
if (dirp == NULL) {
rb_sys_warning(dir);
free(base);
free(magic);
break;
}
}
else {
free(base);
free(magic);
break;
}
@ -747,7 +784,9 @@ glob_helper(path, sub, flags, func, arg)
char *t = buf+strlen(buf);
strcpy(t, "/**");
strcpy(t+3, m);
glob_helper(buf, t, flags, func, arg);
status = glob_helper(buf, t, flags, func, arg);
free(buf);
if (status) goto finalize;
}
free(buf);
continue;
@ -756,8 +795,8 @@ glob_helper(path, sub, flags, func, arg)
buf = ALLOC_N(char, strlen(base)+NAMLEN(dp)+2);
sprintf(buf, "%s%s%s", base, (BASE) ? "/" : "", dp->d_name);
if (!m) {
(*func)(buf, arg);
free(buf);
status = glob_call_func(func, path, arg);
if (status) goto finalize;
continue;
}
tmp = ALLOC(struct d_link);
@ -766,24 +805,27 @@ glob_helper(path, sub, flags, func, arg)
link = tmp;
}
}
finalize:
closedir(dirp);
free(base);
free(magic);
if (link) {
while (link) {
if (stat(link->path, &st) == 0) {
if (S_ISDIR(st.st_mode)) {
int len = strlen(link->path);
int mlen = strlen(m);
char *t = ALLOC_N(char, len+mlen+1);
if (status == 0) {
if (stat(link->path, &st) == 0) {
if (S_ISDIR(st.st_mode)) {
int len = strlen(link->path);
int mlen = strlen(m);
char *t = ALLOC_N(char, len+mlen+1);
sprintf(t, "%s%s", link->path, m);
glob_helper(t, t+len, flags, func, arg);
free(t);
sprintf(t, "%s%s", link->path, m);
status = glob_helper(t, t+len, flags, func, arg);
free(t);
}
}
else {
rb_sys_warning(link->path);
}
}
else {
rb_sys_warning(link->path);
}
tmp = link;
link = link->next;
@ -795,6 +837,7 @@ glob_helper(path, sub, flags, func, arg)
}
p = m;
}
return status;
}
static void
@ -804,7 +847,8 @@ rb_glob2(path, flags, func, arg)
void (*func) _((const char*, VALUE));
VALUE arg;
{
glob_helper(path, 0, flags, func, arg);
int status = glob_helper(path, 0, flags, func, arg);
if (status) rb_jump_tag(status);
}
void

View File

@ -2841,6 +2841,7 @@ class TkWindow<TkObject
end
def destroy
super
tk_call 'destroy', epath
if @cmdtbl
for id in @cmdtbl

134
string.c
View File

@ -236,44 +236,10 @@ rb_str_shared_replace(str, str2)
RSTRING(str2)->ptr = 0; /* abandon str2 */
RSTRING(str2)->len = 0;
RSTRING(str2)->aux.capa = 0;
FL_UNSET(str, ELTS_SHARED|STR_ASSOC);
FL_UNSET(str2, ELTS_SHARED|STR_ASSOC);
if (OBJ_TAINTED(str2)) OBJ_TAINT(str);
}
void
rb_str_associate(str, add)
VALUE str, add;
{
if (FL_TEST(str, STR_ASSOC)) {
/* already associated */
rb_ary_concat(RSTRING(str)->aux.shared, add);
}
else {
if (FL_TEST(str, ELTS_SHARED)) {
rb_str_modify(str);
}
else if (RSTRING(str)->aux.shared) {
/* str_buf */
if (RSTRING(str)->aux.capa != RSTRING(str)->len) {
RESIZE_CAPA(str, RSTRING(str)->len);
}
}
RSTRING(str)->aux.shared = add;
FL_UNSET(str, ELTS_SHARED);
FL_SET(str, STR_ASSOC);
}
}
VALUE
rb_str_associated(str)
VALUE str;
{
if (FL_TEST(str, STR_ASSOC)) {
return RSTRING(str)->aux.shared;
}
return Qfalse;
}
static ID id_to_s;
VALUE
@ -433,6 +399,36 @@ rb_str_modify(str)
str_make_independent(str);
}
void
rb_str_associate(str, add)
VALUE str, add;
{
if (FL_TEST(str, STR_ASSOC)) {
/* already associated */
rb_ary_concat(RSTRING(str)->aux.shared, add);
}
else {
if (FL_TEST(str, ELTS_SHARED)) {
str_make_independent(str);
}
else if (RSTRING(str)->aux.capa != RSTRING(str)->len) {
RESIZE_CAPA(str, RSTRING(str)->len);
}
RSTRING(str)->aux.shared = add;
FL_SET(str, STR_ASSOC);
}
}
VALUE
rb_str_associated(str)
VALUE str;
{
if (FL_TEST(str, STR_ASSOC)) {
return RSTRING(str)->aux.shared;
}
return Qfalse;
}
VALUE
rb_string_value(ptr)
volatile VALUE *ptr;
@ -514,9 +510,11 @@ rb_str_resize(str, len)
if (len != RSTRING(str)->len) {
rb_str_modify(str);
if (RSTRING(str)->len < len || RSTRING(str)->len - len > 1024) {
RESIZE_CAPA(str, len);
REALLOC_N(RSTRING(str)->ptr, char, len+1);
if (!FL_TEST(str, STR_ASSOC)) {
RSTRING(str)->aux.capa = len;
}
}
RSTRING(str)->len = len;
RSTRING(str)->ptr[len] = '\0'; /* sentinel */
@ -532,10 +530,18 @@ rb_str_buf_cat(str, ptr, len)
{
long capa, total;
if (FL_TEST(str, ELTS_SHARED)) {
rb_str_modify(str);
if (len == 0) return str;
if (len < 0) {
rb_raise(rb_eArgError, "negative string size (or size too big)");
}
rb_str_modify(str);
if (FL_TEST(str, STR_ASSOC)) {
FL_UNSET(str, STR_ASSOC);
capa = RSTRING(str)->aux.capa = RSTRING(str)->len;
}
else {
capa = RSTRING(str)->aux.capa;
}
capa = RSTRING(str)->aux.capa;
total = RSTRING(str)->len+len;
if (capa <= total) {
while (total > capa) {
@ -564,12 +570,12 @@ rb_str_cat(str, ptr, len)
const char *ptr;
long len;
{
rb_str_modify(str);
if (len > 0) {
if (!FL_TEST(str, ELTS_SHARED) && !FL_TEST(str, STR_ASSOC)) {
return rb_str_buf_cat(str, ptr, len);
}
RESIZE_CAPA(str, RSTRING(str)->len + len);
if (len < 0) {
rb_raise(rb_eArgError, "negative string size (or size too big)");
}
if (FL_TEST(str, STR_ASSOC)) {
rb_str_modify(str);
REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+len);
if (ptr) {
memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
}
@ -578,9 +584,10 @@ rb_str_cat(str, ptr, len)
}
RSTRING(str)->len += len;
RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
return str;
}
return str;
return rb_str_buf_cat(str, ptr, len);
}
VALUE
@ -597,11 +604,14 @@ rb_str_buf_append(str, str2)
{
long capa, len;
if (FL_TEST(str, ELTS_SHARED)) {
rb_str_modify(str);
rb_str_modify(str);
if (FL_TEST(str, STR_ASSOC)) {
FL_UNSET(str, STR_ASSOC);
capa = RSTRING(str)->aux.capa = RSTRING(str)->len;
}
else {
capa = RSTRING(str)->aux.capa;
}
capa = RSTRING(str)->aux.capa;
len = RSTRING(str)->len+RSTRING(str2)->len;
if (capa <= len) {
while (len > capa) {
@ -613,6 +623,7 @@ rb_str_buf_append(str, str2)
RSTRING(str2)->ptr, RSTRING(str2)->len);
RSTRING(str)->len += RSTRING(str2)->len;
RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
OBJ_INFECT(str, str2);
return str;
}
@ -626,20 +637,19 @@ rb_str_append(str, str2)
StringValue(str2);
rb_str_modify(str);
if (RSTRING(str2)->len > 0) {
len = RSTRING(str)->len+RSTRING(str2)->len;
if (!FL_TEST(str, ELTS_SHARED) && !FL_TEST(str, STR_ASSOC)) {
rb_str_buf_append(str, str2);
OBJ_INFECT(str, str2);
return str;
if (FL_TEST(str, STR_ASSOC)) {
len = RSTRING(str)->len+RSTRING(str2)->len;
REALLOC_N(RSTRING(str)->ptr, char, len+1);
memcpy(RSTRING(str)->ptr + RSTRING(str)->len,
RSTRING(str2)->ptr, RSTRING(str2)->len);
RSTRING(str)->ptr[len] = '\0'; /* sentinel */
RSTRING(str)->len = len;
}
else {
return rb_str_buf_append(str, str2);
}
RESIZE_CAPA(str, len);
memcpy(RSTRING(str)->ptr + RSTRING(str)->len,
RSTRING(str2)->ptr, RSTRING(str2)->len);
RSTRING(str)->len += RSTRING(str2)->len;
RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
}
OBJ_INFECT(str, str2);
return str;
}