From d630684687d764b2d2d8fe030f430c25eb9784ec Mon Sep 17 00:00:00 2001 From: nobu Date: Mon, 30 Oct 2006 14:23:46 +0000 Subject: * 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/branches/ruby_1_8@11245 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 ++++++ dir.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++------------ win32/win32.c | 59 +++++++++++++++++++++++++++++++++------------- 3 files changed, 110 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index 82f9680fb1..4172bb2673 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Mon Oct 30 23:22:43 2006 Nobuyoshi Nakada + + * 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:29:20 2006 NAKAMURA Usaku * bignum.c (rb_big2str0): use better approximation. diff --git a/dir.c b/dir.c index fd677c898d..4ac9ca6953 100644 --- a/dir.c +++ b/dir.c @@ -158,7 +158,7 @@ fnmatch(pat, string, flags) int period = !(flags & FNM_DOTMATCH); int nocase = flags & FNM_CASEFOLD; - while (c = *pat++) { + while ((c = *pat++) != '\0') { switch (c) { case '?': if (!*s || ISDIRSEP(*s) || PERIOD(s)) @@ -821,7 +821,12 @@ sys_warning_1(mesg) #define GLOB_VERBOSE (1U << (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_REALLOC_N(var, type, n) (type *)realloc((var), sizeof(type) * (n)) +#define GLOB_JUMP_TAG(status) ((status == -1) ? rb_memerror() : rb_jump_tag(status)) /* Return nonzero if S has any special globbing chars in it. */ static int @@ -872,7 +877,8 @@ extract_path(p, pend) int len; len = pend - p; - alloc = ALLOC_N(char, len+1); + alloc = GLOB_ALLOC_N(char, len+1); + if (!alloc) return NULL; memcpy(alloc, p, len); if (len > 1 && pend[-1] == '/' #if defined DOSISH_DRIVE_LETTER @@ -955,6 +961,7 @@ glob_helper(path, sub, flags, func, arg) int status = 0; char *buf = 0; char *newpath = 0; + char *newbuf; p = sub ? sub : path; if (!has_magic(p, 0, flags)) { @@ -963,6 +970,7 @@ glob_helper(path, sub, flags, func, arg) #endif { newpath = strdup(path); + if (!newpath) return -1; if (sub) { p = newpath + (sub - path); remove_backslashes(newpath + (sub - path)); @@ -981,7 +989,7 @@ glob_helper(path, sub, flags, func, arg) we may want to know what is wrong. */ sys_warning(path); } - xfree(newpath); + if (newpath) free(newpath); return status; } @@ -1000,10 +1008,18 @@ glob_helper(path, sub, flags, func, arg) } *tmp, *link, **tail = &link; base = extract_path(path, p); + if (!base) { + status = -1; + break; + } if (path == p) dir = "."; else dir = base; magic = extract_elem(p); + if (!magic) { + status = -1; + break; + } if (stat(dir, &st) < 0) { if (errno != ENOENT) sys_warning(dir); @@ -1015,7 +1031,12 @@ glob_helper(path, sub, flags, func, arg) if (m && strcmp(magic, "**") == 0) { int n = strlen(base); recursive = 1; - REALLOC_N(buf, char, n+strlen(m)+3); + newbuf = GLOB_REALLOC_N(buf, char, n+strlen(m)+3); + if (!newbuf) { + status = -1; + goto finalize; + } + buf = newbuf; sprintf(buf, "%s%s", base, *base ? m : m+1); status = glob_helper(buf, buf+n, flags, func, arg); if (status) goto finalize; @@ -1046,7 +1067,12 @@ glob_helper(path, sub, flags, func, arg) continue; if (fnmatch("*", dp->d_name, flags) != 0) continue; - REALLOC_N(buf, char, strlen(base)+NAMLEN(dp)+strlen(m)+6); + newbuf = GLOB_REALLOC_N(buf, char, strlen(base)+NAMLEN(dp)+strlen(m)+6); + if (!newbuf) { + status = -1; + break; + } + buf = newbuf; sprintf(buf, "%s%s%s", base, (BASE) ? "/" : "", dp->d_name); if (lstat(buf, &st) < 0) { if (errno != ENOENT) @@ -1064,14 +1090,23 @@ glob_helper(path, sub, flags, func, arg) continue; } if (fnmatch(magic, dp->d_name, flags) == 0) { - REALLOC_N(buf, char, strlen(base)+NAMLEN(dp)+2); + newbuf = GLOB_REALLOC_N(buf, char, strlen(base)+NAMLEN(dp)+2); + if (!newbuf) { + status = -1; + break; + } + buf = newbuf; sprintf(buf, "%s%s%s", base, (BASE) ? "/" : "", dp->d_name); if (!m) { status = glob_call_func(func, buf, arg); if (status) break; continue; } - tmp = ALLOC(struct d_link); + tmp = GLOB_ALLOC(struct d_link); + if (!tmp) { + status = -1; + break; + } tmp->path = buf; buf = 0; *tail = tmp; @@ -1091,7 +1126,12 @@ glob_helper(path, sub, flags, func, arg) int len = strlen(link->path); int mlen = strlen(m); - REALLOC_N(buf, char, len+mlen+1); + newbuf = GLOB_REALLOC_N(buf, char, len+mlen+1); + if (!newbuf) { + status = -1; + goto next_elem; + } + buf = newbuf; sprintf(buf, "%s%s", link->path, m); status = glob_helper(buf, buf+len, flags, func, arg); } @@ -1100,6 +1140,7 @@ glob_helper(path, sub, flags, func, arg) sys_warning(link->path); } } + next_elem: tmp = link; link = link->next; free(tmp->path); @@ -1110,8 +1151,8 @@ glob_helper(path, sub, flags, func, arg) } p = m; } - xfree(buf); - xfree(newpath); + if (buf) free(buf); + if (newpath) free(newpath); return status; } @@ -1211,7 +1252,7 @@ push_braces(ary, str, flags) int flags; { char *buf = 0; - char *b; + char *b, *newbuf; const char *s, *p, *t; const char *lbrace, *rbrace; int nest = 0; @@ -1249,7 +1290,12 @@ push_braces(ary, str, flags) } } } - REALLOC_N(buf, char, len+1); + newbuf = GLOB_REALLOC_N(buf, char, len+1); + if (!newbuf) { + status = -1; + break; + } + buf = newbuf; memcpy(buf, s, lbrace-s); b = buf + (lbrace-s); memcpy(b, t, p-t); @@ -1261,7 +1307,7 @@ push_braces(ary, str, flags) else { status = push_globs(ary, str, flags); } - xfree(buf); + if (buf) free(buf); return status; } @@ -1306,7 +1352,7 @@ rb_push_glob(str, flags) } /* else unmatched braces */ } - if (status) rb_jump_tag(status); + if (status) GLOB_JUMP_TAG(status); if (rb_block_given_p()) { rb_ary_each(ary); return Qnil; diff --git a/win32/win32.c b/win32/win32.c index 0b58c19690..a16aeb5d02 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -431,7 +431,8 @@ getlogin() if (NTLoginName == NULL) { if (GetUserName(buffer, &len)) { - NTLoginName = ALLOC_N(char, len+1); + NTLoginName = (char *)malloc(len+1); + if (!NTLoginName) return NULL; strncpy(NTLoginName, buffer, len); NTLoginName[len] = '\0'; } @@ -1068,10 +1069,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; @@ -1093,20 +1096,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_globi(buf, 0, insert, (VALUE)&tail); + status = ruby_globi(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); @@ -1333,8 +1337,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; @@ -1359,7 +1363,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 @@ -1456,6 +1471,7 @@ rb_w32_opendir(const char *filename) fh = FindFirstFile(scanname, &fd); if (fh == INVALID_HANDLE_VALUE) { errno = map_errno(GetLastError()); + free(p); return NULL; } @@ -1465,7 +1481,13 @@ rb_w32_opendir(const char *filename) // idx = strlen(fd.cFileName)+1; - p->start = ALLOC_N(char, idx); + if (!(p->start = (char *)malloc(idx))) { + error: + rb_w32_closedir(p); + FindClose(fh); + errno = ENOMEM; + return NULL; + } strcpy(p->start, fd.cFileName); p->nfiles++; @@ -1476,6 +1498,8 @@ rb_w32_opendir(const char *filename) // of the previous string found. // while (FindNextFile(fh, &fd)) { + char *newpath; + len = strlen(fd.cFileName); // @@ -1483,12 +1507,11 @@ rb_w32_opendir(const char *filename) // new name and it's null terminator // - #define Renew(x, y, z) (x = (z *)xrealloc(x, y)) - - Renew (p->start, idx+len+1, char); - if (p->start == NULL) { - rb_fatal ("opendir: malloc failed!\n"); + newpath = (char *)realloc(p->start, idx+len+1); + if (newpath == NULL) { + goto error; } + p->start = newpath; strcpy(&p->start[idx], fd.cFileName); p->nfiles++; idx += len+1; @@ -3519,10 +3542,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++; } -- cgit v1.2.3