From: Nobuyoshi Nakada Date: 2007-03-25T00:49:56+09:00 Subject: [ruby-dev:30673] Re: fail to copy argv on Win32? なかだです。 At Sat, 24 Mar 2007 14:58:36 +0900, wanabe wrote in [ruby-dev:30672]: > trunkのrev.12125をmingw32環境で試したところ、ruby -e 'p "1"' で > unterminated string meets end of file と言われてしまいました。 > 一応rev.12124 を参考にパッチを書いてみたのですが、動作を全然理解できていないので > おかしなことをしているかもしれません。 パッチ自体は正しいと思いますが、strlcpy()やstrlcat()を使うべき なのは、木村さんの日記からリンクされている「Pythonも危ない...」 [1]でも書かれているとおり、固定バッファの場合です。win32.cのよ うに、コピー元の長さでバッファを確保してその長さでコピーするよ うな場合は、memcpy()で十分ではないかと思いますし、strdup()のほ うが適切なことも多いのではないでしょうか。 [1] http://blog.ohgaki.net/index.php/yohgaki/2007/03/15/pythona_a_pa_oa Index: win32/win32.c =================================================================== --- win32/win32.c (revision 12127) +++ win32/win32.c (working copy) @@ -402,8 +402,5 @@ init_env(void) return; } - NTLoginName = (char *)malloc(len+1); - if (!NTLoginName) return; - strlcpy(NTLoginName, env, len + 1); - NTLoginName[len] = '\0'; + NTLoginName = strdup(env); } @@ -1057,8 +1054,7 @@ insert(const char *path, VALUE vinfo) MEMZERO(tmpcurr, NtCmdLineElement, 1); tmpcurr->len = strlen(path); - tmpcurr->str = (char *)malloc(tmpcurr->len + 1); + tmpcurr->str = strdup(path); if (!tmpcurr->str) return -1; tmpcurr->flags |= NTMALLOC; - strlcpy(tmpcurr->str, path, tmpcurr->len + 1); **tail = tmpcurr; *tail = &tmpcurr->next; @@ -1085,5 +1081,5 @@ cmdglob(NtCmdLineElement *patt, NtCmdLin if (!(buf = malloc(patt->len + 1))) return 0; - strlcpy(buf, patt->str, patt->len + 1); + memcpy(buf, patt->str, patt->len + 1); buf[patt->len] = '\0'; for (p = buf; *p; p = CharNext(p)) @@ -1374,5 +1370,5 @@ rb_w32_cmdvector(const char *cmd, char * while (curr = cmdhead) { - strlcpy(ptr, curr->str, len - (elements + 1)); + memcpy(ptr, curr->str, curr->len + 1); *vptr++ = ptr; ptr += curr->len + 1; @@ -1437,15 +1433,15 @@ rb_w32_opendir(const char *filename) // Create the search pattern // - len = strlen(filename) + 2 + 1; - if (!(scanname = malloc(len))) { + len = strlen(filename); + if (!(scanname = malloc(len + 2 + 1))) { free(p); return NULL; } - strlcpy(scanname, filename, len); + memcpy(scanname, filename, len + 1); - if (index("/\\:", *CharPrev(scanname, scanname + strlen(scanname))) == NULL) - strlcat(scanname, "/*", len); + if (index("/\\:", *CharPrev(scanname, scanname + len)) == NULL) + memcpy(scanname + len, "/*", 2 + 1); else - strlcat(scanname, "*", len); + memcpy(scanname + len, "*", 1 + 1); // @@ -1472,5 +1468,5 @@ rb_w32_opendir(const char *filename) return NULL; } - strlcpy(p->start, fd.cFileName, idx); + memcpy(p->start, fd.cFileName, idx); p->bits[0] = 0; if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) @@ -1497,5 +1493,5 @@ rb_w32_opendir(const char *filename) goto error; p->start = tmp; - strlcpy(&p->start[idx], fd.cFileName, len); + memcpy(&p->start[idx], fd.cFileName, len); if (p->nfiles % 4 == 0) { @@ -1554,5 +1550,5 @@ rb_w32_readdir(DIR *dirp) if (!(dirp->dirstr.d_name = malloc(dirp->dirstr.d_namlen + 1))) return NULL; - strlcpy(dirp->dirstr.d_name, dirp->curr, dirp->dirstr.d_namlen + 1); + memcpy(dirp->dirstr.d_name, dirp->curr, dirp->dirstr.d_namlen + 1); // @@ -1862,5 +1858,5 @@ rb_w32_strerror(int e) if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, &source, e, 0, - buffer, 512, NULL) == 0) + buffer, sizeof(buffer), NULL) == 0) strlcpy(buffer, "Unknown Error", sizeof(buffer)); } @@ -3459,8 +3455,8 @@ rb_w32_stati64(const char *path, struct *end = '\0'; else if (*end != '\\') - strlcat(buf1, "\\", size); + memcpy(buf1 + len, "\\", 2); } else if (*end == '\\' || (buf1 + 1 == end && *end == ':')) - strlcat(buf1, ".", size); + memcpy(buf1 + len, ".", 2); ret = IsWinNT() ? winnt_stat(buf1, st) : stati64(buf1, st); @@ -3916,9 +3912,7 @@ rb_w32_get_environ(void) for (env = envtop, myenv = myenvtop; *env; env += strlen(env) + 1) { if (*env != '=') { - int len = strlen(env) + 1; - if (!(*myenv = (char *)malloc(len))) { + if (!(*myenv = strdup(env))) { break; } - strlcpy(*myenv, env, len); myenv++; } -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦