From d7bcd2a16f4dfad45357c57bc6334db51652215e Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Mon, 13 Feb 2012 13:12:37 +0000 Subject: [PATCH] * Makefile.in (clean): Remove non-existant regexp dir. * collate.h: New header. (__collate_range_cmp): Declare. (__collate_load_error): Define. * glob.cc: Pull in latest version from FreeBSD. Simplify and reduce Cygwin-specific changes. * regex/regcomp.c: Include collate.h on Cygwin as well. (__collate_range_cmp): Move from here... * nlsfuncs.cc (__collate_range_cmp): ...to here. * miscfuncs.cc (thread_wrapper): Fix typo in comment. (CygwinCreateThread): Take dead zone of Windows stack into account. Change the way how the stack is commited and how to handle guardpages. Explain how and why. * thread.h (PTHREAD_DEFAULT_STACKSIZE): Change definition. Explain why. --- winsup/cygwin/ChangeLog | 19 +++++ winsup/cygwin/Makefile.in | 2 +- winsup/cygwin/collate.h | 23 ++++++ winsup/cygwin/glob.cc | 145 +++++++++++++++------------------- winsup/cygwin/miscfuncs.cc | 67 ++++++++++------ winsup/cygwin/nlsfuncs.cc | 9 +++ winsup/cygwin/regex/regcomp.c | 13 --- winsup/cygwin/thread.h | 10 ++- 8 files changed, 167 insertions(+), 121 deletions(-) create mode 100644 winsup/cygwin/collate.h diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 15f89532f..aae667650 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,22 @@ +2012-02-13 Corinna Vinschen + + * Makefile.in (clean): Remove non-existant regexp dir. + + * collate.h: New header. + (__collate_range_cmp): Declare. + (__collate_load_error): Define. + * glob.cc: Pull in latest version from FreeBSD. Simplify and reduce + Cygwin-specific changes. + * regex/regcomp.c: Include collate.h on Cygwin as well. + (__collate_range_cmp): Move from here... + * nlsfuncs.cc (__collate_range_cmp): ...to here. + + * miscfuncs.cc (thread_wrapper): Fix typo in comment. + (CygwinCreateThread): Take dead zone of Windows stack into account. + Change the way how the stack is commited and how to handle guardpages. + Explain how and why. + * thread.h (PTHREAD_DEFAULT_STACKSIZE): Change definition. Explain why. + 2012-02-12 Yaakov Selkowitz * include/pthread.h: Include time.h as required by POSIX. diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index c3310cf01..4830e40d5 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -383,7 +383,7 @@ uninstall-man: done clean: - -rm -f *.o *.dll *.dbg *.a *.exp junk *.base version.cc regexp/*.o winver_stamp *.exe *.d *stamp* *_magic.h sigfe.s cygwin.def globals.h $(srcdir)/tlsoffsets.h $(srcdir)/devices.cc + -rm -f *.o *.dll *.dbg *.a *.exp junk *.base version.cc winver_stamp *.exe *.d *stamp* *_magic.h sigfe.s cygwin.def globals.h $(srcdir)/tlsoffsets.h $(srcdir)/devices.cc -@$(MAKE) -C $(bupdir)/cygserver libclean maintainer-clean realclean: clean diff --git a/winsup/cygwin/collate.h b/winsup/cygwin/collate.h new file mode 100644 index 000000000..3cfb8880c --- /dev/null +++ b/winsup/cygwin/collate.h @@ -0,0 +1,23 @@ +/* collate.h: Internal BSD libc header, used in glob and regcomp, for instance. + + Copyright 2012 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* We never have a collate load error. */ +const int __collate_load_error = 0; + +int __collate_range_cmp (int c1, int c2); + +#ifdef __cplusplus +}; +#endif diff --git a/winsup/cygwin/glob.cc b/winsup/cygwin/glob.cc index 6bb97c19a..b732f14c5 100644 --- a/winsup/cygwin/glob.cc +++ b/winsup/cygwin/glob.cc @@ -33,9 +33,8 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; #endif /* LIBC_SCCS and not lint */ -#ifdef __CYGWIN -__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/gen/glob.c,v 1.25 2006/06/05 18:22:13 delphij Exp $"); -#endif +#include +__FBSDID("$FreeBSD: src/lib/libc/gen/glob.c,v 1.28 2010/05/12 17:44:00 gordon Exp $"); /* * glob(3) -- a superset of the one defined in POSIX 1003.2. @@ -72,35 +71,45 @@ __FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/gen/glob.c,v 1.25 2006/06/05 18 * 3. State-dependent encodings are not currently supported. */ +#ifdef __CYGWIN__ #include "winsup.h" +#endif +#include +#include #include #include +#include #include +#include #include +#include +#include #include +#include #include #include -//#include "collate.h" +#include "collate.h" -#include "cygerrno.h" -#include "security.h" +#ifdef __CYGWIN__ +#include #include "path.h" #include "fhandler.h" #include "dtable.h" - #include "cygheap.h" -#include "perprocess.h" #include "cygwin/version.h" -#ifndef ARG_MAX -#define ARG_MAX 32000 /* See CreateProcess */ -#endif +#define getpwuid(uid) getpwuid32 (uid) +#define getuid() getuid32 () +#define issetugid() (cygheap->user.issetuid ()) -#undef MAXPATHLEN -#define MAXPATHLEN 16384 +#define stat __stat64 + +#define CCHAR(c) (ignore_case_with_glob ? towlower (CHAR (c)) : CHAR (c)) +#define Cchar(c) (ignore_case_with_glob ? towlower (c) : (c)) +#endif #define DOLLAR '$' #define DOT '.' @@ -154,19 +163,19 @@ typedef char Char; static int compare(const void *, const void *); static int g_Ctoc(const Char *, char *, size_t); -static int g_lstat(Char *, struct __stat64 *, glob_t *); +static int g_lstat(Char *, struct stat *, glob_t *); static DIR *g_opendir(Char *, glob_t *); -static Char *g_strchr(Char *, wchar_t); +static const Char *g_strchr(const Char *, wchar_t); #ifdef notdef static Char *g_strcat(Char *, const Char *); #endif -static int g_stat(Char *, struct __stat64 *, glob_t *); +static int g_stat(Char *, struct stat *, glob_t *); static int glob0(const Char *, glob_t *, size_t *); static int glob1(Char *, glob_t *, size_t *); static int glob2(Char *, Char *, Char *, Char *, glob_t *, size_t *); static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, size_t *); static int globextend(const Char *, glob_t *, size_t *); -static const Char * +static const Char * globtilde(const Char *, Char *, size_t, glob_t *); static int globexp1(const Char *, glob_t *, size_t *); static int globexp2(const Char *, const Char *, glob_t *, int *, size_t *); @@ -259,7 +268,7 @@ globexp1(const Char *pattern, glob_t *pglob, size_t *limit) if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) return glob0(pattern, pglob, limit); - while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) + while ((ptr = g_strchr(ptr, LBRACE)) != NULL) if (!globexp2(ptr, pattern, pglob, &rv, limit)) return rv; @@ -387,8 +396,8 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) return pattern; - /* - * Copy up to the end of the string or / + /* + * Copy up to the end of the string or / */ eb = &patbuf[patbuf_len - 1]; for (p = pattern + 1, h = (char *) patbuf; @@ -403,11 +412,11 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) * we're not running setuid or setgid) and then trying * the password file */ - if (cygheap->user.issetuid() != 0 || + if (issetugid() != 0 || (h = getenv("HOME")) == NULL) { if (((h = getlogin()) != NULL && (pwd = getpwnam(h)) != NULL) || - (pwd = getpwuid32(getuid32())) != NULL) + (pwd = getpwuid(getuid())) != NULL) h = pwd->pw_dir; else return pattern; @@ -448,7 +457,7 @@ glob0(const Char *pattern, glob_t *pglob, size_t *limit) const Char *qpatnext; int err; size_t oldpathc; - Char c, *bufnext, patbuf[MAXPATHLEN]; + Char *bufnext, c, patbuf[MAXPATHLEN]; qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); oldpathc = pglob->gl_pathc; @@ -462,7 +471,7 @@ glob0(const Char *pattern, glob_t *pglob, size_t *limit) if (c == NOT) ++qpatnext; if (*qpatnext == EOS || - g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { + g_strchr(qpatnext+1, RBRACKET) == NULL) { *bufnext++ = LBRACKET; if (c == NOT) --qpatnext; @@ -556,7 +565,7 @@ static int glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern, glob_t *pglob, size_t *limit) { - struct __stat64 sb; + struct stat sb; Char *p, *q; int anymeta; @@ -625,6 +634,8 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last, * assigned, below, to two functions which are prototyped in glob.h * and dirent.h as taking pointers to differently typed opaque * structures. + * CYGWIN: Needs prototype and subsequently wild casting to avoid + * compiler error. */ struct dirent *(*readdirfunc)(void *); @@ -642,7 +653,7 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last, pglob->gl_flags & GLOB_ERR) return (GLOB_ABORTED); } - return((pglob->gl_flags & GLOB_ERR) ? GLOB_ABORTED : 0); + return(0); } err = 0; @@ -786,41 +797,23 @@ match(Char *name, Char *pat, Char *patend) return(0); if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) ++pat; - if (ignore_case_with_glob) - { - while (((c = *pat++) & M_MASK) != M_END) + while (((c = *pat++) & M_MASK) != M_END) if ((*pat & M_MASK) == M_RNG) { - if (tolower(c) <= tolower(k) && tolower(k) <= tolower(pat[1])) - ok = 1; - pat += 2; - } else if (tolower(c) == tolower(k)) - ok = 1; - } - else - { - while (((c = *pat++) & M_MASK) != M_END) - if ((*pat & M_MASK) == M_RNG) { - if (c <= k && k <= pat[1]) - ok = 1; - pat += 2; + if (__collate_load_error ? + CCHAR(c) <= CCHAR(k) && CCHAR(k) <= CCHAR(pat[1]) : + __collate_range_cmp(CCHAR(c), CCHAR(k)) <= 0 + && __collate_range_cmp(CCHAR(k), CCHAR(pat[1])) <= 0 + ) + ok = 1; + pat += 2; } else if (c == k) - ok = 1; - } + ok = 1; if (ok == negate_range) return(0); break; default: - if (ignore_case_with_glob) - { - if (tolower(*name) != tolower(c)) - return(0); - ++name; - } - else - { - if (*name++ != c) + if (Cchar(*name++) != Cchar(c)) return(0); - } break; } } @@ -881,8 +874,18 @@ stat32_to_stat64 (struct __stat32 *src, struct __stat64 *dst) dst->st_blocks = src->st_blocks; } +#define CYGWIN_gl_stat(sfptr) \ + ({ int ret; \ + struct __stat32 lsb; \ + if (CYGWIN_VERSION_CHECK_FOR_USING_BIG_TYPES) \ + ret = (*pglob->sfptr) (buf, sb); \ + else if (!(ret = (*pglob->sfptr) (buf, (struct __stat64 *) &lsb))) \ + stat32_to_stat64 (&lsb, sb); \ + ret; \ + }) + static int -g_lstat(Char *fn, struct __stat64 *sb, glob_t *pglob) +g_lstat(Char *fn, struct stat *sb, glob_t *pglob) { char buf[MAXPATHLEN]; @@ -890,22 +893,13 @@ g_lstat(Char *fn, struct __stat64 *sb, glob_t *pglob) errno = ENAMETOOLONG; return (-1); } - if (pglob->gl_flags & GLOB_ALTDIRFUNC) { - struct __stat32 lsb; - int ret; - - if (CYGWIN_VERSION_CHECK_FOR_USING_BIG_TYPES) - ret = (*pglob->gl_lstat)(buf, sb); - else if (!(ret = (*pglob->gl_lstat)(buf, - (struct __stat64 *)&lsb))) - stat32_to_stat64 (&lsb, sb); - return ret; - } + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return CYGWIN_gl_stat (gl_lstat); return(lstat64(buf, sb)); } static int -g_stat(Char *fn, struct __stat64 *sb, glob_t *pglob) +g_stat(Char *fn, struct stat *sb, glob_t *pglob) { char buf[MAXPATHLEN]; @@ -913,22 +907,13 @@ g_stat(Char *fn, struct __stat64 *sb, glob_t *pglob) errno = ENAMETOOLONG; return (-1); } - if (pglob->gl_flags & GLOB_ALTDIRFUNC) { - struct __stat32 lsb; - int ret; - - if (CYGWIN_VERSION_CHECK_FOR_USING_BIG_TYPES) - ret = (*pglob->gl_stat)(buf, sb); - else if (!(ret = (*pglob->gl_stat)(buf, - (struct __stat64 *)&lsb))) - stat32_to_stat64 (&lsb, sb); - return ret; - } + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return CYGWIN_gl_stat (gl_stat); return(stat64(buf, sb)); } -static Char * -g_strchr(Char *str, wchar_t ch) +static const Char * +g_strchr(const Char *str, wchar_t ch) { do { diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index 53ae58571..3743ead65 100644 --- a/winsup/cygwin/miscfuncs.cc +++ b/winsup/cygwin/miscfuncs.cc @@ -527,7 +527,7 @@ thread_wrapper (VOID *arg) xorl %%ebp, %%ebp # Set ebp to 0 \n\ # Make gcc 3.x happy and align the stack so that it is \n\ # 16 byte aligned right before the final call opcode. \n\ - andl $-16, %%esp # 16 bit align \n\ + andl $-16, %%esp # 16 byte align \n\ addl $-12, %%esp # 12 bytes + 4 byte arg = 16 \n\ # Now we moved to the new stack. Save thread func address\n\ # and thread arg on new stack \n\ @@ -578,11 +578,17 @@ CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg, } else { + char *commitaddr; + /* If not, we have to create the stack here. */ real_stacksize = roundup2 (stacksize, wincap.page_size ()); real_guardsize = roundup2 (guardsize, wincap.page_size ()); /* Add the guardsize to the stacksize */ real_stacksize += real_guardsize; + /* If we use the default Windows guardpage method, we have to take + the 2 pages dead zone into account. */ + if (real_guardsize == wincap.page_size ()) + real_stacksize += 2 * wincap.page_size (); /* Now roundup the result to the next allocation boundary. */ real_stacksize = roundup2 (real_stacksize, wincap.allocation_granularity ()); @@ -596,28 +602,43 @@ CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg, PAGE_READWRITE); if (!real_stackaddr) return NULL; - /* Set up committed region. In contrast to the OS we commit 64K and - set up just a single guard page at the end. */ - char *commitaddr = (char *) real_stackaddr - + real_stacksize - - wincap.allocation_granularity (); - if (!VirtualAlloc (commitaddr, wincap.page_size (), MEM_COMMIT, - PAGE_READWRITE | PAGE_GUARD)) - goto err; - commitaddr += wincap.page_size (); - if (!VirtualAlloc (commitaddr, wincap.allocation_granularity () - - wincap.page_size (), MEM_COMMIT, - PAGE_READWRITE)) - goto err; - /* If the guardsize is != 0 (which is the default), set up a POSIX - guardpage at the end of the stack. This isn't the same as the - Windows guardpage, which is used to convert reserved stack to - commited stack if necessary. Rather, the POSIX guardpage consists - of one or more memory pages with NOACCESS protection. It's supposed - to safeguard memory areas beyond the stack against stack overflow. */ - if (real_guardsize) - VirtualAlloc (real_stackaddr, real_guardsize, MEM_COMMIT, - PAGE_NOACCESS); + /* Set up committed region. Two cases: */ + if (real_guardsize != wincap.page_size ()) + { + /* If guardsize is set to something other than the page size, we + commit the entire stack and, if guardsize is > 0, we set up a + POSIX guardpage. We don't set up a Windows guardpage. */ + if (!VirtualAlloc (real_stackaddr, real_guardsize, MEM_COMMIT, + PAGE_NOACCESS)) + goto err; + commitaddr = (char *) real_stackaddr + real_guardsize; + if (!VirtualAlloc (commitaddr, real_stacksize - real_guardsize, + MEM_COMMIT, PAGE_READWRITE)) + goto err; + } + else + { + /* If guardsize is exactly the page_size, we can assume that the + application will behave Windows conformant in terms of stack usage. + We can especially assume that it never allocates more than one + page at a time (alloca/_chkstk). Therefore, this is the default + case which allows a Windows compatible stack setup with a + reserved region, a guard page, and a commited region. We don't + need to set up a POSIX guardpage since Windows already handles + stack overflow: Trying to extend the stack into the last three + pages of the stack results in a SEGV. + We always commit 64K here, starting with the guardpage. */ + commitaddr = (char *) real_stackaddr + real_stacksize + - wincap.allocation_granularity (); + if (!VirtualAlloc (commitaddr, wincap.page_size (), MEM_COMMIT, + PAGE_READWRITE | PAGE_GUARD)) + goto err; + commitaddr += wincap.page_size (); + if (!VirtualAlloc (commitaddr, wincap.allocation_granularity () + - wincap.page_size (), MEM_COMMIT, + PAGE_READWRITE)) + goto err; + } wrapper_arg->stackaddr = (char *) real_stackaddr; wrapper_arg->stackbase = (char *) real_stackaddr + real_stacksize; wrapper_arg->commitaddr = commitaddr; diff --git a/winsup/cygwin/nlsfuncs.cc b/winsup/cygwin/nlsfuncs.cc index 61255dfc3..00c834e55 100644 --- a/winsup/cygwin/nlsfuncs.cc +++ b/winsup/cygwin/nlsfuncs.cc @@ -1192,6 +1192,15 @@ strcoll (const char *s1, const char *s2) return ret - CSTR_EQUAL; } +/* BSD. Used in glob.cc and regcomp.c, for instance. */ +extern "C" int +__collate_range_cmp (int c1, int c2) +{ + char s1[2] = { c1, '\0' }; + char s2[2] = { c2, '\0' }; + return strcoll (s1, s2); +} + extern "C" size_t wcsxfrm (wchar_t *ws1, const wchar_t *ws2, size_t wsn) { diff --git a/winsup/cygwin/regex/regcomp.c b/winsup/cygwin/regex/regcomp.c index 5aee63948..30502f7f1 100644 --- a/winsup/cygwin/regex/regcomp.c +++ b/winsup/cygwin/regex/regcomp.c @@ -55,9 +55,7 @@ __FBSDID("$FreeBSD: src/lib/libc/regex/regcomp.c,v 1.36 2007/06/11 03:05:54 delp #include #include -#ifndef __CYGWIN__ #include "collate.h" -#endif #include "utils.h" #include "regex2.h" @@ -771,17 +769,6 @@ p_bracket(struct parse *p) EMIT(OANYOF, (int)(cs - p->g->sets)); } -#ifdef __CYGWIN__ -/* This function is usually part of FreeBSD's libc. */ -int -__collate_range_cmp(int c1, int c2) -{ - char s1[2] = { c1, '\0' }; - char s2[2] = { c2, '\0' }; - return strcoll (s1, s2); -} -#endif - /* - p_b_term - parse one term of a bracketed character list == static void p_b_term(struct parse *p, cset *cs); diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index 9adc9e1c7..ec3ca7ebf 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -16,10 +16,12 @@ details. */ #define WRITE_LOCK 1 #define READ_LOCK 2 -/* Default is a 1 Megs stack with a 4K guardpage. Since the pthread stacksize - does not include the guardpage size, but we don't want to waste another 64K, - subtract the default guardpage size from the stacksize. */ -#define PTHREAD_DEFAULT_STACKSIZE (1024 * 1024 - wincap.page_size ()) +/* Default is a 1 Megs stack with a 4K guardpage. The pthread stacksize + does not include the guardpage size, so we subtract the default guardpage + size. Additionally, the Windows stack handling disallows to use the last + two pages as guard page (tested on XP and W7). That results in a zone of + three pages which have to be subtract to get the actual stack size. */ +#define PTHREAD_DEFAULT_STACKSIZE (1024 * 1024 - 3 * wincap.page_size ()) #define PTHREAD_DEFAULT_GUARDSIZE (wincap.page_size ()) #include