diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-10-30 14:23:46 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-10-30 14:23:46 +0000 |
commit | 66d43b5fd6f97289b907f60be52246f8abc82b4b (patch) | |
tree | 15ee7cf1b38e2a092de5723eafc9cebbc4828bc3 | |
parent | 3679754a95df33dd576cf9f81ae2ef70a84a6649 (diff) | |
download | ruby-66d43b5fd6f97289b907f60be52246f8abc82b4b.tar.gz |
* dir.c (glob_helper): get rid of possible memory leak.
* win32/win32.c (cmdglob, rb_w32_cmdvector, rb_w32_opendir,
rb_w32_get_environ): not to use GC before initialization.
[ruby-core:09024]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11245 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | dir.c | 78 | ||||
-rw-r--r-- | win32/win32.c | 53 |
3 files changed, 108 insertions, 30 deletions
@@ -1,3 +1,10 @@ +Mon Oct 30 23:22:43 2006 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * dir.c (glob_helper): get rid of possible memory leak. + + * win32/win32.c (cmdglob, rb_w32_cmdvector, rb_w32_opendir, + rb_w32_get_environ): not to use GC before initialization. + Mon Oct 30 19:28:02 2006 NAKAMURA Usaku <usa@ruby-lang.org> * bignum.c (rb_big2str0): use better approximation. @@ -922,7 +922,11 @@ sys_warning_1(const char* mesg) #define GLOB_VERBOSE (1UL << (sizeof(int) * CHAR_BIT - 1)) #define sys_warning(val) \ - ((flags & GLOB_VERBOSE) && rb_protect((VALUE (*)_((VALUE)))sys_warning_1, (VALUE)(val), 0)) + (void)((flags & GLOB_VERBOSE) && rb_protect((VALUE (*)_((VALUE)))sys_warning_1, (VALUE)(val), 0)) + +#define GLOB_ALLOC(type) (type *)malloc(sizeof(type)) +#define GLOB_ALLOC_N(type, n) (type *)malloc(sizeof(type) * (n)) +#define GLOB_JUMP_TAG(status) ((status == -1) ? rb_memerror() : rb_jump_tag(status)) /* System call with warning */ static int @@ -1058,6 +1062,8 @@ struct glob_pattern { struct glob_pattern *next; }; +static void glob_free_pattern(struct glob_pattern *list); + static struct glob_pattern * glob_make_pattern(const char *p, int flags) { @@ -1065,7 +1071,8 @@ glob_make_pattern(const char *p, int flags) int dirsep = 0; /* pattern is terminated with '/' */ while (*p) { - tmp = ALLOC(struct glob_pattern); + tmp = GLOB_ALLOC(struct glob_pattern); + if (!tmp) goto error; if (p[0] == '*' && p[1] == '*' && p[2] == '/') { /* fold continuous RECURSIVEs (needed in glob_helper) */ do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/'); @@ -1075,7 +1082,11 @@ glob_make_pattern(const char *p, int flags) } else { const char *m = find_dirsep(p, flags); - char *buf = ALLOC_N(char, m-p+1); + char *buf = GLOB_ALLOC_N(char, m-p+1); + if (!buf) { + free(tmp); + goto error; + } memcpy(buf, p, m-p); buf[m-p] = '\0'; tmp->type = has_magic(buf, flags) ? MAGICAL : PLAIN; @@ -1093,7 +1104,13 @@ glob_make_pattern(const char *p, int flags) tail = &tmp->next; } - tmp = ALLOC(struct glob_pattern); + tmp = GLOB_ALLOC(struct glob_pattern); + if (!tmp) { + error: + *tail = 0; + glob_free_pattern(list); + return 0; + } tmp->type = dirsep ? MATCH_DIR : MATCH_ALL; tmp->str = 0; *tail = tmp; @@ -1118,8 +1135,9 @@ static char * join_path(const char *path, int dirsep, const char *name) { long len = strlen(path); - char *buf = ALLOC_N(char, len+strlen(name)+(dirsep?1:0)+1); + char *buf = GLOB_ALLOC_N(char, len+strlen(name)+(dirsep?1:0)+1); + if (!buf) return 0; memcpy(buf, path, len); if (dirsep) { strcpy(buf+len, "/"); @@ -1229,6 +1247,7 @@ glob_helper( } if (match_dir && isdir == YES) { char *tmp = join_path(path, dirsep, ""); + if (!tmp) return -1; status = glob_call_func(func, tmp, arg); free(tmp); if (status) return status; @@ -1244,8 +1263,12 @@ glob_helper( for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { char *buf = join_path(path, dirsep, dp->d_name); - enum answer new_isdir = UNKNOWN; + + if (!buf) { + status = -1; + break; + } if (recursive && strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0 && fnmatch("*", dp->d_name, flags) == 0) { #ifndef _WIN32 @@ -1258,7 +1281,11 @@ glob_helper( #endif } - new_beg = new_end = ALLOC_N(struct glob_pattern *, (end - beg) * 2); + new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, (end - beg) * 2); + if (!new_beg) { + status = -1; + break; + } for (cur = beg; cur < end; ++cur) { struct glob_pattern *p = *cur; @@ -1284,7 +1311,8 @@ glob_helper( else if (plain) { struct glob_pattern **copy_beg, **copy_end, **cur2; - copy_beg = copy_end = ALLOC_N(struct glob_pattern *, end - beg); + copy_beg = copy_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg); + if (!copy_beg) return -1; for (cur = beg; cur < end; ++cur) *copy_end++ = (*cur)->type == PLAIN ? *cur : 0; @@ -1292,11 +1320,20 @@ glob_helper( if (*cur) { char *buf; char *name; - name = ALLOC_N(char, strlen((*cur)->str) + 1); + name = GLOB_ALLOC_N(char, strlen((*cur)->str) + 1); + if (!name) { + status = -1; + break; + } strcpy(name, (*cur)->str); if (escape) remove_backslashes(name); - new_beg = new_end = ALLOC_N(struct glob_pattern *, end - beg); + new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg); + if (!new_beg) { + free(name); + status = -1; + break; + } *new_end++ = (*cur)->next; for (cur2 = cur + 1; cur2 < copy_end; ++cur2) { if (*cur2 && fnmatch((*cur2)->str, name, flags) == 0) { @@ -1307,6 +1344,11 @@ glob_helper( buf = join_path(path, dirsep, name); free(name); + if (!buf) { + free(new_beg); + status = -1; + break; + } status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg, new_end, flags, func, arg); free(buf); free(new_beg); @@ -1338,11 +1380,16 @@ ruby_glob0(const char *path, int flags, ruby_glob_func *func, VALUE arg) if (root && *root == '/') root++; n = root - start; - buf = ALLOC_N(char, n + 1); + buf = GLOB_ALLOC_N(char, n + 1); + if (!buf) return -1; MEMCPY(buf, start, char, n); buf[n] = '\0'; list = glob_make_pattern(root, flags); + if (!list) { + free(buf); + return -1; + } status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg); glob_free_pattern(list); free(buf); @@ -1386,7 +1433,7 @@ void rb_glob(const char *path, void (*func)(const char *, VALUE), VALUE arg) { int status = rb_glob2(path, 0, func, arg); - if (status) rb_jump_tag(status); + if (status) GLOB_JUMP_TAG(status); } static void @@ -1419,9 +1466,10 @@ ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg) } if (lbrace && rbrace) { - char *buf = ALLOC_N(char, strlen(s) + 1); + char *buf = GLOB_ALLOC_N(char, strlen(s) + 1); long shift; + if (!buf) return -1; memcpy(buf, s, lbrace-s); shift = (lbrace-s); p = lbrace; @@ -1503,7 +1551,7 @@ rb_push_glob(VALUE str, int flags) /* '\0' is delimiter */ while (offset < RSTRING_LEN(str)) { int status = push_glob(ary, RSTRING_PTR(str) + offset, flags); char *p, *pend; - if (status) rb_jump_tag(status); + if (status) GLOB_JUMP_TAG(status); if (offset >= RSTRING_LEN(str)) break; p = RSTRING_PTR(str) + offset; p += strlen(p) + 1; @@ -1527,7 +1575,7 @@ dir_globs(long argc, VALUE *argv, int flags) VALUE str = argv[i]; StringValue(str); status = push_glob(ary, RSTRING_PTR(str), flags); - if (status) rb_jump_tag(status); + if (status) GLOB_JUMP_TAG(status); } return ary; diff --git a/win32/win32.c b/win32/win32.c index 7c7f310bb0..a8e755e1ff 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -410,7 +410,8 @@ init_env(void) NTLoginName = "<Unknown>"; return; } - NTLoginName = ALLOC_N(char, len+1); + NTLoginName = (char *)malloc(len+1); + if (!NTLoginName) return; strncpy(NTLoginName, env, len); NTLoginName[len] = '\0'; } @@ -1059,10 +1060,12 @@ insert(const char *path, VALUE vinfo) NtCmdLineElement *tmpcurr; NtCmdLineElement ***tail = (NtCmdLineElement ***)vinfo; - tmpcurr = ALLOC(NtCmdLineElement); + tmpcurr = (NtCmdLineElement *)malloc(sizeof(NtCmdLineElement)); + if (!tmpcurr) return -1; MEMZERO(tmpcurr, NtCmdLineElement, 1); tmpcurr->len = strlen(path); - tmpcurr->str = ALLOC_N(char, tmpcurr->len + 1); + tmpcurr->str = (char *)malloc(tmpcurr->len + 1); + if (!tmpcurr->str) return -1; tmpcurr->flags |= NTMALLOC; strcpy(tmpcurr->str, path); **tail = tmpcurr; @@ -1084,20 +1087,21 @@ cmdglob(NtCmdLineElement *patt, NtCmdLineElement **tail) char buffer[MAXPATHLEN], *buf = buffer; char *p; NtCmdLineElement **last = tail; + int status; if (patt->len >= MAXPATHLEN) - buf = ruby_xmalloc(patt->len + 1); + if (!(buf = malloc(patt->len + 1))) return 0; strncpy (buf, patt->str, patt->len); buf[patt->len] = '\0'; for (p = buf; *p; p = CharNext(p)) if (*p == '\\') *p = '/'; - ruby_brace_glob(buf, 0, insert, (VALUE)&tail); + status = ruby_brace_glob(buf, 0, insert, (VALUE)&tail); if (buf != buffer) free(buf); - if (last == tail) return 0; + if (status || last == tail) return 0; if (patt->flags & NTMALLOC) free(patt->str); free(patt); @@ -1321,8 +1325,8 @@ rb_w32_cmdvector(const char *cmd, char ***vec) } } - curr = ALLOC(NtCmdLineElement); - MEMZERO(curr, NtCmdLineElement, 1); + curr = (NtCmdLineElement *)calloc(sizeof(NtCmdLineElement), 1); + if (!curr) goto do_nothing; curr->str = base; curr->len = len; @@ -1347,7 +1351,18 @@ rb_w32_cmdvector(const char *cmd, char ***vec) } len = (elements+1)*sizeof(char *) + strsz; - buffer = ALLOC_N(char, len); + buffer = (char *)malloc(len); + if (!buffer) { + do_nothing: + while (curr = cmdhead) { + cmdhead = curr->next; + if (curr->flags & NTMALLOC) free(curr->str); + free(curr); + } + free(cmdline); + for (vptr = *vec; *vptr; ++vptr); + return vptr - *vec; + } // // make vptr point to the start of the buffer @@ -1447,6 +1462,7 @@ rb_w32_opendir(const char *filename) fh = FindFirstFile(scanname, &fd); if (fh == INVALID_HANDLE_VALUE) { errno = map_errno(GetLastError()); + free(p); return NULL; } @@ -1456,9 +1472,14 @@ rb_w32_opendir(const char *filename) // idx = strlen(fd.cFileName)+1; - p->start = ALLOC_N(char, idx); + if (!(p->start = (char *)malloc(idx)) || !(p->bits = (char *)malloc(1))) { + error: + rb_w32_closedir(p); + FindClose(fh); + errno = ENOMEM; + return NULL; + } strcpy(p->start, fd.cFileName); - p->bits = ALLOC_N(char, 1); p->bits[0] = 0; if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) SetBit(p->bits, 0); @@ -1484,14 +1505,14 @@ rb_w32_opendir(const char *filename) Renew (p->start, idx+len+1, char); if (p->start == NULL) { - rb_fatal ("opendir: malloc failed!\n"); + goto error; } strcpy(&p->start[idx], fd.cFileName); if (p->nfiles % 4 == 0) { Renew (p->bits, p->nfiles / 4 + 1, char); if (p->bits == NULL) { - rb_fatal ("opendir: malloc failed!\n"); + goto error; } p->bits[p->nfiles / 4] = 0; } @@ -3981,10 +4002,12 @@ rb_w32_get_environ(void) for (env = envtop, num = 0; *env; env += strlen(env) + 1) if (*env != '=') num++; - myenvtop = ALLOC_N(char*, num + 1); + myenvtop = (char **)malloc(sizeof(char *) * (num + 1)); for (env = envtop, myenv = myenvtop; *env; env += strlen(env) + 1) { if (*env != '=') { - *myenv = ALLOC_N(char, strlen(env) + 1); + if (!(*myenv = (char *)malloc(strlen(env) + 1))) { + break; + } strcpy(*myenv, env); myenv++; } |