aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog20
-rw-r--r--dir.c86
-rw-r--r--ext/tk/lib/tk.rb1
-rw-r--r--string.c134
4 files changed, 158 insertions, 83 deletions
diff --git a/ChangeLog b/ChangeLog
index 7479d1507e..77153b1eab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/dir.c b/dir.c
index 5f6e707a81..72ce949b24 100644
--- a/dir.c
+++ b/dir.c
@@ -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);
-
- sprintf(t, "%s%s", link->path, m);
- glob_helper(t, t+len, flags, func, arg);
- free(t);
+ 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);
+ 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
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index bc9cb0676f..736a12fd26 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -2841,6 +2841,7 @@ class TkWindow<TkObject
end
def destroy
+ super
tk_call 'destroy', epath
if @cmdtbl
for id in @cmdtbl
diff --git a/string.c b/string.c
index 3149ad7167..60d0cce202 100644
--- a/string.c
+++ b/string.c
@@ -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;
}