From 7c5ac499c84648ef1f58afa1187656f5d72c56d8 Mon Sep 17 00:00:00 2001 From: Francesco Montorsi Date: Tue, 13 Jan 2009 12:01:30 +0000 Subject: [PATCH] provide our own implementation of wxStrnlen if it's not available; add tests for it git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58069 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- configure | 96 +----------------------------------------- configure.in | 3 +- include/wx/wxcrt.h | 29 ++++++++++--- include/wx/wxcrtbase.h | 3 ++ setup.h.in | 3 ++ tests/strings/crt.cpp | 43 ++++++++++++++++++- 6 files changed, 75 insertions(+), 102 deletions(-) diff --git a/configure b/configure index a96ef63669..7cfe3dba7c 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Id: configure.in 58039 2009-01-12 14:26:13Z VZ . +# From configure.in Id: configure.in 58060 2009-01-12 23:25:39Z FM . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for wxWidgets 2.9.0. # @@ -34955,101 +34955,9 @@ _ACEOF fi -for ac_func in wcsdup -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif - -int -main () -{ -return $ac_func (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_var=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_var'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done -for ac_func in strnlen +for ac_func in wcsdup strnlen wcsnlen do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 diff --git a/configure.in b/configure.in index 87ce064dc2..208271592d 100644 --- a/configure.in +++ b/configure.in @@ -4047,8 +4047,7 @@ if test "$wxUSE_WCHAR_T" = "yes"; then AC_DEFINE(HAVE_WCSLEN) fi - AC_CHECK_FUNCS([wcsdup]) - AC_CHECK_FUNCS([strnlen]) + AC_CHECK_FUNCS([wcsdup strnlen wcsnlen]) dnl On HP-UX aCC need this define to find mbstrtowcs() &c dnl Can't be used for g++ since the mbstate_t in wchar.h can conflict diff --git a/include/wx/wxcrt.h b/include/wx/wxcrt.h index ca5c694e66..662ea9758d 100644 --- a/include/wx/wxcrt.h +++ b/include/wx/wxcrt.h @@ -182,14 +182,33 @@ inline size_t wxStrlen(const wxString& s) { return s.length(); } inline size_t wxStrlen(const wxCStrData& s) { return s.AsString().length(); } // this is a function new in 2.9 so we don't care about backwards compatibility and -// so don't need to support wchar_t/char overloads -#if defined(wxCRT_StrnlenA) && defined(wxCRT_StrnlenW) +// so don't need to support wxCharBuffer/wxWCharBuffer overloads +#if defined(wxCRT_StrnlenA) inline size_t wxStrnlen(const char *str, size_t maxlen) { return wxCRT_StrnlenA(str, maxlen); } +#else +inline size_t wxStrnlen(const char *str, size_t maxlen) +{ + size_t n; + for ( n = 0; n < maxlen; n++ ) + if ( !str[n] ) + break; + + return n; +} +#endif + +#if defined(wxCRT_StrnlenW) inline size_t wxStrnlen(const wchar_t *str, size_t maxlen) { return wxCRT_StrnlenW(str, maxlen); } #else -// use unsafer wxStrlen: -inline size_t wxStrnlen(const char *str, size_t maxlen) { return wxCRT_StrlenA(str); wxUnusedVar(maxlen); } -inline size_t wxStrnlen(const wchar_t *str, size_t maxlen) { return wxCRT_StrlenW(str); wxUnusedVar(maxlen); } +inline size_t wxStrnlen(const wchar_t *str, size_t maxlen) +{ + size_t n; + for ( n = 0; n < maxlen; n++ ) + if ( !str[n] ) + break; + + return n; +} #endif // NB: these are defined in wxcrtbase.h, see the comment there diff --git a/include/wx/wxcrtbase.h b/include/wx/wxcrtbase.h index 45cb175d69..67f69da6ce 100644 --- a/include/wx/wxcrtbase.h +++ b/include/wx/wxcrtbase.h @@ -225,6 +225,9 @@ WXDLLIMPEXP_BASE void *calloc( size_t num, size_t size ); /* Not all compilers have strnlen(); e.g. MSVC 6.x and 7.x don't have it */ #if wxCHECK_VISUALC_VERSION(8) || defined(HAVE_STRNLEN) #define wxCRT_StrnlenA strnlen +#endif + +#if wxCHECK_VISUALC_VERSION(8) || defined(HAVE_WCSNLEN) #define wxCRT_StrnlenW wcsnlen #endif diff --git a/setup.h.in b/setup.h.in index 39369fadf1..8b7365d7b8 100644 --- a/setup.h.in +++ b/setup.h.in @@ -921,6 +921,9 @@ /* Define if you have strnlen() function */ #undef HAVE_STRNLEN +/* Define if you have wcsnlen() function */ +#undef HAVE_WCSNLEN + /* Define if you have wcstoull() and wcstoll() */ #undef HAVE_WCSTOULL diff --git a/tests/strings/crt.cpp b/tests/strings/crt.cpp index 150ae7cab1..8855068748 100644 --- a/tests/strings/crt.cpp +++ b/tests/strings/crt.cpp @@ -4,7 +4,7 @@ // Author: Vaclav Slavik // Created: 2004-06-03 // RCS-ID: $Id$ -// Copyright: (c) 2004 Vaclav Slavik +// Copyright: (c) 2004 Vaclav Slavik // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -48,6 +48,7 @@ private: CPPUNIT_TEST( Strspn ); CPPUNIT_TEST( Strcspn ); CPPUNIT_TEST( Strpbrk ); + CPPUNIT_TEST( Strnlen ); CPPUNIT_TEST_SUITE_END(); void SetGetEnv(); @@ -55,6 +56,7 @@ private: void Strspn(); void Strcspn(); void Strpbrk(); + void Strnlen(); DECLARE_NO_COPY_CLASS(CrtTestCase) }; @@ -209,3 +211,42 @@ void CrtTestCase::Strpbrk() CPPUNIT_ASSERT_EQUAL( (wchar_t *)NULL, wxStrpbrk(strWX.c_str(), L"xyz") ); } +void CrtTestCase::Strnlen() +{ + // the following calls should not segfault/crash because when passing 0 + // as maxlen, no bytes at all should be read from the given buffer + // (which is NULL in this case!) + CPPUNIT_ASSERT_EQUAL( (size_t)0, wxStrnlen((const char*)NULL, 0) ); + CPPUNIT_ASSERT_EQUAL( (size_t)0, wxStrnlen((const wchar_t*)NULL, 0) ); + + // other misc tests for wxStrnlen(const char*, size_t) + + CPPUNIT_ASSERT_EQUAL( (size_t)0, wxStrnlen("", 0) ); + CPPUNIT_ASSERT_EQUAL( (size_t)0, wxStrnlen("", 8) ); + CPPUNIT_ASSERT_EQUAL( (size_t)0, wxStrnlen("1234", 0) ); + CPPUNIT_ASSERT_EQUAL( (size_t)2, wxStrnlen("1234", 2) ); + CPPUNIT_ASSERT_EQUAL( (size_t)4, wxStrnlen("1234", 8) ); + CPPUNIT_ASSERT_EQUAL( (size_t)7, wxStrnlen("1234567", 8) ); + CPPUNIT_ASSERT_EQUAL( (size_t)8, wxStrnlen("12345678", 8) ); + CPPUNIT_ASSERT_EQUAL( (size_t)8, wxStrnlen("123456789", 8) ); + CPPUNIT_ASSERT_EQUAL( (size_t)9, wxStrnlen("123456789", 12) ); + + // other misc tests for wxStrnlen(const wchar_t*, size_t) + + CPPUNIT_ASSERT_EQUAL( (size_t)0, wxStrnlen(L"", 0) ); + CPPUNIT_ASSERT_EQUAL( (size_t)0, wxStrnlen(L"", 8) ); + CPPUNIT_ASSERT_EQUAL( (size_t)0, wxStrnlen(L"1234", 0) ); + CPPUNIT_ASSERT_EQUAL( (size_t)2, wxStrnlen(L"1234", 2) ); + CPPUNIT_ASSERT_EQUAL( (size_t)4, wxStrnlen(L"1234", 8) ); + CPPUNIT_ASSERT_EQUAL( (size_t)7, wxStrnlen(L"1234567", 8) ); + CPPUNIT_ASSERT_EQUAL( (size_t)8, wxStrnlen(L"12345678", 8) ); + CPPUNIT_ASSERT_EQUAL( (size_t)8, wxStrnlen(L"123456789", 8) ); + CPPUNIT_ASSERT_EQUAL( (size_t)9, wxStrnlen(L"123456789", 12) ); + + // wxStrlen() is only for NULL-terminated strings: + CPPUNIT_ASSERT_EQUAL( (size_t)4, wxStrnlen("1234" "\0" "78", 12) ); + CPPUNIT_ASSERT_EQUAL( (size_t)4, wxStrnlen(L"1234" L"\0" L"5678", 12) ); +} + + + -- 2.47.2