Return-Path: Delivered-To: apmail-incubator-stdcxx-dev-archive@www.apache.org Received: (qmail 61542 invoked from network); 8 Aug 2006 15:01:42 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 8 Aug 2006 15:01:42 -0000 Received: (qmail 22054 invoked by uid 500); 8 Aug 2006 15:01:41 -0000 Delivered-To: apmail-incubator-stdcxx-dev-archive@incubator.apache.org Received: (qmail 22039 invoked by uid 500); 8 Aug 2006 15:01:41 -0000 Mailing-List: contact stdcxx-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: stdcxx-dev@incubator.apache.org Delivered-To: mailing list stdcxx-dev@incubator.apache.org Received: (qmail 22028 invoked by uid 99); 8 Aug 2006 15:01:41 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 08 Aug 2006 08:01:41 -0700 X-ASF-Spam-Status: No, hits=0.0 required=10.0 tests= X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [212.82.213.172] (HELO exkiv.kyiv.vdiweb.com) (212.82.213.172) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 08 Aug 2006 08:01:40 -0700 Received: from [10.11.37.198] ([10.11.37.198]) by exkiv.kyiv.vdiweb.com with Microsoft SMTPSVC(6.0.3790.1830); Tue, 8 Aug 2006 18:01:37 +0300 Message-ID: <44D8A74F.3060604@kyiv.vdiweb.com> Date: Tue, 08 Aug 2006 18:01:35 +0300 From: Farid Zaripov User-Agent: Thunderbird 1.5.0.5 (Windows/20060719) MIME-Version: 1.0 To: stdcxx-dev@incubator.apache.org Subject: RE: rw_match can address to memory after end of string buffer Content-Type: multipart/mixed; boundary="------------050803040502070002090909" X-OriginalArrivalTime: 08 Aug 2006 15:01:37.0463 (UTC) FILETIME=[8BFA4470:01C6BAFB] X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N --------------050803040502070002090909 Content-Type: text/plain; charset=KOI8-R; format=flowed Content-Transfer-Encoding: 7bit > -----Original Message----- > From: Martin Sebor [mailto:sebor@roguewave.com] > Sent: Monday, July 10, 2006 1:59 AM > To: stdcxx-dev@incubator.apache.org > Subject: Re: rw_match can address to memory after end of string buffer > [...] > > >> Hmm, that does look like a subtle bug in rw_match(). Let > me look into > >> how best to fix it. > > The commit below should fix it. I'm not 100% happy with the > code and suspect there might still be some bugs lurking in > there but if they are there the current test doesn't reveal > them (even under Sun dbx with memory checking on) and none of > the string tests is showing any signs of problems either. > http://svn.apache.org/viewvc?rev=420363&view=rev The bug with addressing after the end of string still present. I updated the test 0.char.cpp to check this bug. The diff file is attached. ChangeLog: * 0.char.cpp: (test_rw_match): the test strings allocated at the protected memory to detect addressing after end of the string. Farid. --------------050803040502070002090909 Content-Type: text/plain; name="0.char.cpp.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="0.char.cpp.diff" Index: 0.char.cpp =================================================================== --- 0.char.cpp (revision 429612) +++ 0.char.cpp (working copy) @@ -27,10 +27,35 @@ #include #include #include +#include // for rw_alloc(), rw_free() #include // for free() #include // for memset(), size_t, strlen() +#include // for signal() +#include // for setjmp(), longjmp() +#ifdef sigsetjmp +#define SETJMP(env) sigsetjmp(env, 1) +#else +#define SETJMP(env) setjmp(env) +#endif + +#define BEGIN_TEST_OVERRUN() \ + (signal (SIGSEGV, sig_handler), \ + (0 == SETJMP (mark))) + +static jmp_buf mark; + +extern "C" { + +static void +sig_handler (int) +{ + longjmp (mark, -1); +} + +} + /***********************************************************************/ static void @@ -750,7 +775,15 @@ return 0; } +// using mymemcpy to hide g++ warning: +// null argument where non-null required (argument 2) +static inline void* +mymemcpy (void* dst, const void* src, size_t count) +{ + return memcpy (dst, src, count); +} + static void test_rw_match () { @@ -759,14 +792,43 @@ size_t result; +#define IF_PREPARE_TEST(str1, size1, str2, size2, type) \ + if (true) { \ + const size_t sz1 = str1 ? size1 : 0; \ + void* s1 = sz1 ? rw_alloc (sz1, RW_PROT_RDWR) : 0; \ + RW_ASSERT (s1 && sz1 || !(s1 || sz1)); \ + mymemcpy (s1, str1, sz1); \ + size_t sz2 = str2 ? size2 : 0; \ + void* s2 = sz2 ? rw_alloc (sz2, RW_PROT_RDWR) : 0; \ + RW_ASSERT (s2 && sz2 || !(s2 || sz2)); \ + mymemcpy (s2, str2, sz2); \ + sz2 /= sizeof (type); \ + if (BEGIN_TEST_OVERRUN ()) + +#define CLEANUP_TEST() \ + rw_free (s1); \ + rw_free (s2); \ + } \ + else + #undef TEST -#define TEST(s1, s2, len, expect) \ - result = rw_match ((const char*)s1, (const char*)s2, size_t (len)); \ - rw_assert (expect == result, \ - 0, __LINE__, \ - "rw_match(%{#*s}, %{#*s}, %zu) == %zu, got %zu", \ - int (sizeof s1 - 1), s1, int (sizeof s2 - 1), s2, len, \ - expect, result) +#define TEST(str1, str2, len, expect) \ + IF_PREPARE_TEST(str1, sizeof (str1), str2, sizeof (str2), char) { \ + result = rw_match ((const char*)s1, (const char*)s2, size_t (len)); \ + rw_assert (expect == result, \ + 0, __LINE__, \ + "rw_match(%{#*s}, %{#*s}, %zu) == %zu, got %zu", \ + int (sz1 ? sz1 - 1 : 0), s1, \ + int (sz2 ? sz2 - 1 : 0), s2, len, \ + expect, result); \ + } \ + else \ + rw_assert (0, 0, __LINE__, \ + "rw_match(%{#*s}, %{#*s}, %zu) addressed after " \ + "end of string", \ + int (sz1 ? sz1 - 1 : 0), s1, \ + int (sz2 ? sz2 - 1 : 0), s2, len); \ + CLEANUP_TEST() TEST (0, 0, -1, 0); TEST ("", 0, -1, 0); @@ -906,24 +968,53 @@ TEST ("A@3A", "AAAAA", -1, 6); TEST ("@0@1@2@3", "BCCDDD", -1, 7); + #else // unknown rw_warn (0, 0, "unknown character set (neither ASCII nor EBCDIC)"); #endif +#undef TEST +#define TEST(ch1, ch2, expect) \ + IF_PREPARE_TEST(&ch1, 1, &ch2, 1, char) { \ + result = rw_match ((const char*)s1, (const char*)s2, 1); \ + rw_assert (expect == result, \ + 0, __LINE__, \ + "rw_match(&\'%c\', &\'%c\', 1) == %zu, got %zu", \ + ch1, ch2, expect, result); \ + } \ + else \ + rw_assert (0, 0, __LINE__, \ + "rw_match(&\'%c\', &\'%c\', 1) addressed after " \ + "end of string", \ + ch1, ch2); \ + CLEANUP_TEST() + + char ch = 'a'; + TEST (ch, ch, 1); + ////////////////////////////////////////////////////////////////// rw_info (0, 0, 0, "rw_match(char*, const wchar_t*, size_t)"); #ifndef _RWSTD_NO_WCHAR_T #undef TEST -#define TEST(s1, s2, len, expect) \ - result = rw_match ((const char*)s1, (const wchar_t*)s2, size_t (len)); \ - rw_assert (expect == result, \ - 0, __LINE__, \ - "rw_match(%{#*s}, L%{#*ls}, %zu) == %zu, got %zu", \ - int (sizeof s1 - 1), s1, \ - int (sizeof (s2) / sizeof *(s2) - 1), s2, len, \ - expect, result) +#define TEST(str1, str2, len, expect) \ + IF_PREPARE_TEST(str1, sizeof (str1), str2, sizeof (str2), wchar_t) { \ + result = rw_match ((const char*)s1, (const wchar_t*)s2, size_t (len)); \ + rw_assert (expect == result, \ + 0, __LINE__, \ + "rw_match(%{#*s}, L%{#*ls}, %zu) == %zu, got %zu", \ + int (sz1 ? sz1 - 1 : 0), s1, \ + int (sz2 ? sz2 - 1 : 0), s2, len, \ + expect, result); \ + } \ + else \ + rw_assert (0, 0, __LINE__, \ + "rw_match(%{#*s}, L%{#*ls}, %zu) addressed after " \ + "end of string", \ + int (sz1 ? sz1 - 1 : 0), s1, \ + int (sz2 ? sz2 - 1 : 0), s2, len); \ + CLEANUP_TEST() TEST (0, (wchar_t*)0, -1, 0); TEST ("", (wchar_t*)0, -1, 0); @@ -1009,6 +1100,25 @@ TEST ("a@b", L"a@b", -1, 4); TEST ("a@b@c", L"a@b@c", -1, 6); +#undef TEST +#define TEST(ch1, ch2, expect) \ + IF_PREPARE_TEST(&ch1, 1, &ch2, sizeof (wchar_t), wchar_t) { \ + result = rw_match ((const char*)s1, (const wchar_t*)s2, 1); \ + rw_assert (expect == result, \ + 0, __LINE__, \ + "rw_match(&\'%c\', &\'%lc\', 1) == %zu, got %zu", \ + ch1, ch2, expect, result); \ + } \ + else \ + rw_assert (0, 0, __LINE__, \ + "rw_match(&\'%c\', &\'%lc\', 1) addressed after " \ + "end of string", \ + ch1, ch2); \ + CLEANUP_TEST() + + wchar_t wch = L'a'; + TEST (ch, wch, 1); + #else // if defined (_RWSTD_NO_WCHAR_T) rw_note (0, 0, 0, "_RWSTD_NO_WCHAR_T #defined, wchar_t test disabled"); @@ -1018,15 +1128,30 @@ ////////////////////////////////////////////////////////////////// rw_info (0, 0, 0, "rw_match(char*, const UserChar*, size_t)"); + const UserChar* ustr; + #undef TEST -#define TEST(s1, s2, len, expect) \ - result = rw_match ((const char*)s1, \ - make_user_string (s2, sizeof (s2)), size_t (len)); \ - rw_assert (expect == result, \ - 0, __LINE__, \ - "rw_match(%{#*s}, %{#*s}, %zu) == %zu, got %zu", \ - int (sizeof s1 - 1), s1, int (sizeof s2 - 1), s2, len, \ - expect, result) +#define TEST(str1, str2, len, expect) \ + ustr = make_user_string (str2, sizeof (str2)); \ + IF_PREPARE_TEST(str1, sizeof (str1), ustr, \ + sizeof (str2) * sizeof (UserChar), \ + UserChar) { \ + result = rw_match ((const char*)s1, \ + (const UserChar*)s2, size_t (len)); \ + rw_assert (expect == result, \ + 0, __LINE__, \ + "rw_match(%{#*s}, %{#*s}, %zu) == %zu, got %zu", \ + int (sz1 ? sz1 - 1 : 0), s1, \ + int (sz2 ? sz2 - 1 : 0), str2, len, \ + expect, result); \ + } \ + else \ + rw_assert (0, 0, __LINE__, \ + "rw_match(%{#*s}, %{#*s}, %zu) addressed after " \ + "end of string", \ + int (sz1 ? sz1 - 1 : 0), s1, \ + int (sz2 ? sz2 - 1 : 0), str2, len); \ + CLEANUP_TEST() TEST (0, 0, -1, 0); TEST ("", 0, -1, 0); @@ -1053,6 +1178,8 @@ TEST ("a", "", -1, 0); TEST ("a", "a", -1, 2); + //TEST (single_char, single_char, 1, 1); + // same as above but using the @ directive TEST ("a@1", "", -1, 0); TEST ("a@1", "a", -1, 2); @@ -1101,6 +1228,27 @@ // invalid directives TEST ("a@b", "a@b", -1, 4); TEST ("a@b@c", "a@b@c", -1, 6); + + UserChar uch; + +#undef TEST +#define TEST(ch1, ch2, expect) \ + uch = make_char (ch2, (UserChar*)0); \ + IF_PREPARE_TEST(&ch1, 1, &uch, sizeof (UserChar), UserChar) { \ + result = rw_match ((const char*)s1, (const UserChar*)s2, 1); \ + rw_assert (expect == result, \ + 0, __LINE__, \ + "rw_match(&\'%c\', &\'%c\', 1) == %zu, got %zu", \ + ch1, ch2, expect, result); \ + } \ + else \ + rw_assert (0, 0, __LINE__, \ + "rw_match(&\'%c\', &\'%c\', 1) addressed after " \ + "end of string", \ + ch1, ch2); \ + CLEANUP_TEST() + + TEST (ch, ch, 1); } /***********************************************************************/ --------------050803040502070002090909--