http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51772
Bug #: 51772 Summary: --enable-clocale=generic makes unsafe assumptions about ctype_base::mask Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: r...@gcc.gnu.org Blocks: 51018 config/locale/generic/ctype_members.cc initializes _M_bit like so: for (size_t __i = 0; __i <= 15; ++__i) { _M_bit[__i] = static_cast<mask>(1 << __i); _M_wmask[__i] = _M_convert_to_wmask(_M_bit[__i]); } This assumes that ctype_base::mask is at least 16 bits. Each element of _M_bit has a single bit set, and is compared to the defined mask constants in _M_convert_to_wmask: ctype<wchar_t>::__wmask_type ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const throw() { __wmask_type __ret; switch (__m) { // ... case xdigit: __ret = wctype("xdigit"); break; case alnum: __ret = wctype("alnum"); break; case graph: __ret = wctype("graph"); break; default: __ret = __wmask_type(); } return __ret; }; If any of the mask constants has more than one bit set it will never be matched. e.g. on NetBSD xdigit can never be matched for ctype<wchar_t> because config/os/bsd/netbsd/ctype_base.h defines the following typedef unsigned char mask; static const mask xdigit = _N | _X; As a result, this valid program aborts: #include <locale> #include <assert.h> class gnu_ctype: public std::ctype<wchar_t> { }; int main() { gnu_ctype gctype; assert(gctype.is(std::ctype_base::xdigit, L'a')); }