mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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:
parent
e78e79e10f
commit
b031fdbc0e
4 changed files with 157 additions and 82 deletions
20
ChangeLog
20
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.
|
||||
|
|
64
dir.c
64
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,11 +805,13 @@ glob_helper(path, sub, flags, func, arg)
|
|||
link = tmp;
|
||||
}
|
||||
}
|
||||
finalize:
|
||||
closedir(dirp);
|
||||
free(base);
|
||||
free(magic);
|
||||
if (link) {
|
||||
while (link) {
|
||||
if (status == 0) {
|
||||
if (stat(link->path, &st) == 0) {
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
int len = strlen(link->path);
|
||||
|
@ -778,13 +819,14 @@ glob_helper(path, sub, flags, func, arg)
|
|||
char *t = ALLOC_N(char, len+mlen+1);
|
||||
|
||||
sprintf(t, "%s%s", link->path, m);
|
||||
glob_helper(t, t+len, flags, func, arg);
|
||||
status = glob_helper(t, t+len, flags, func, arg);
|
||||
free(t);
|
||||
}
|
||||
}
|
||||
else {
|
||||
rb_sys_warning(link->path);
|
||||
}
|
||||
}
|
||||
tmp = link;
|
||||
link = link->next;
|
||||
free(tmp->path);
|
||||
|
@ -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
|
||||
|
|
|
@ -2841,6 +2841,7 @@ class TkWindow<TkObject
|
|||
end
|
||||
|
||||
def destroy
|
||||
super
|
||||
tk_call 'destroy', epath
|
||||
if @cmdtbl
|
||||
for id in @cmdtbl
|
||||
|
|
122
string.c
122
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;
|
||||
}
|
||||
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);
|
||||
if (len < 0) {
|
||||
rb_raise(rb_eArgError, "negative string size (or size too big)");
|
||||
}
|
||||
RESIZE_CAPA(str, RSTRING(str)->len + len);
|
||||
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);
|
||||
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;
|
||||
|
||||
}
|
||||
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) {
|
||||
if (FL_TEST(str, STR_ASSOC)) {
|
||||
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;
|
||||
}
|
||||
RESIZE_CAPA(str, len);
|
||||
REALLOC_N(RSTRING(str)->ptr, char, len+1);
|
||||
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 */
|
||||
RSTRING(str)->ptr[len] = '\0'; /* sentinel */
|
||||
RSTRING(str)->len = len;
|
||||
}
|
||||
else {
|
||||
return rb_str_buf_append(str, str2);
|
||||
}
|
||||
}
|
||||
OBJ_INFECT(str, str2);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue