> -----Original Message-----
> From: Martin Sebor [mailto:[EMAIL PROTECTED]
> Sent: Friday, July 14, 2006 12:07 AM
> To: [email protected]
> Subject: Re: Environment for the test of the string functions
> memory overrun with example
>
[...]
>
> Okay, this version is closer to what I have in mind :) There
> are a few minor tweaks that I would still make but I think
> it's ready to commit as is (please go ahead and have Anton do
> it). We can make the tweaks later (we will also need a test
> to exercise this).
[...]
I have updated the rw_alloc.h and alloc.cpp according to your comments.
Anton commited this version
(http://svn.apache.org/viewvc?rev=421918&view=rev).
Also I wrote the test to exercise the rw_alloc() function
(tests/self/0.alloc.cpp). The test is attached.
Farid.
/************************************************************************
*
* 0.alloc.cpp - test exercising the rw_alloc() and rw_free() functions
*
* $Id: 0.alloc.cpp
*
************************************************************************
*
* Copyright 2006 The Apache Software Foundation or its licensors,
* as applicable.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**************************************************************************/
#include <signal.h> // for signal
#include <setjmp.h> // for setjmp, longjmp
#include <rw_alloc.h> // for rw_alloc, rw_free
#include <rw_printf.h> // for rw_printf
#include <driver.h>
#ifdef __CYGWIN__
// use the Windows API on Cygwin
# define _WIN32
#endif
static jmp_buf mark;
static void sig_handler (int)
{
longjmp (mark, -1);
}
#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))
struct TestCase
{
size_t size_;
int index_;
int prot_;
const char* file_;
int line_;
};
void test (const TestCase& tcase)
{
if (void* buf = rw_alloc (tcase.size_, tcase.prot_)) {
char* str = _RWSTD_STATIC_CAST (char*, buf);
bool protbelow = 0 != (tcase.prot_ & RW_PROT_BELOW);
bool canread = (tcase.prot_ &
#if defined (_WIN32) || defined (_WIN64)
(RW_PROT_READ | RW_PROT_WRITE | RW_PROT_EXEC))
#else
(RW_PROT_READ | RW_PROT_EXEC))
#endif
&& (
(protbelow && 0 <= tcase.index_)
|| (!protbelow && tcase.index_ < int (tcase.size_))
);
bool canwrite = (tcase.prot_ & RW_PROT_WRITE)
&& (
(protbelow && 0 <= tcase.index_)
|| (!protbelow && tcase.index_ < int (tcase.size_))
);
char c = 'a';
if (BEGIN_TEST_OVERRUN ()) {
c = str[tcase.index_];
rw_assert (canread, tcase.file_, tcase.line_,
"expected no read access, got read access");
} else
rw_assert (!canread, tcase.file_, tcase.line_,
"expected read access, got no read access");
if (BEGIN_TEST_OVERRUN ()) {
str[tcase.index_] = c;
rw_assert (canwrite, tcase.file_, tcase.line_,
"expected no write access, got write access");
} else
rw_assert (!canwrite, tcase.file_, tcase.line_,
"expected write access, got no write access");
rw_free (buf);
}
}
static int
run_test (int, char**)
{
const size_t BUF_SIZE = 10;
static const TestCase tcases[] = {
#ifdef TEST
#undef TEST
#endif
#define TEST(size, index, prot) \
{ size, index, prot, __FILE__, __LINE__ }
TEST(BUF_SIZE, -1, RW_PROT_NONE),
TEST(BUF_SIZE, -1, RW_PROT_READ),
TEST(BUF_SIZE, -1, RW_PROT_WRITE),
TEST(BUF_SIZE, -1, RW_PROT_EXEC),
TEST(BUF_SIZE, -1, RW_PROT_NONE | RW_PROT_BELOW),
TEST(BUF_SIZE, -1, RW_PROT_READ | RW_PROT_BELOW),
TEST(BUF_SIZE, -1, RW_PROT_WRITE | RW_PROT_BELOW),
TEST(BUF_SIZE, -1, RW_PROT_EXEC | RW_PROT_BELOW),
TEST(BUF_SIZE, 0, RW_PROT_NONE),
TEST(BUF_SIZE, 0, RW_PROT_READ),
TEST(BUF_SIZE, 0, RW_PROT_WRITE),
TEST(BUF_SIZE, 0, RW_PROT_EXEC),
TEST(BUF_SIZE, 0, RW_PROT_NONE | RW_PROT_BELOW),
TEST(BUF_SIZE, 0, RW_PROT_READ | RW_PROT_BELOW),
TEST(BUF_SIZE, 0, RW_PROT_WRITE | RW_PROT_BELOW),
TEST(BUF_SIZE, 0, RW_PROT_EXEC | RW_PROT_BELOW),
TEST(BUF_SIZE, BUF_SIZE, RW_PROT_NONE | RW_PROT_BELOW),
TEST(BUF_SIZE, BUF_SIZE, RW_PROT_READ | RW_PROT_BELOW),
TEST(BUF_SIZE, BUF_SIZE, RW_PROT_WRITE | RW_PROT_BELOW),
TEST(BUF_SIZE, BUF_SIZE, RW_PROT_EXEC | RW_PROT_BELOW),
TEST(BUF_SIZE, BUF_SIZE, RW_PROT_NONE),
TEST(BUF_SIZE, BUF_SIZE, RW_PROT_READ),
TEST(BUF_SIZE, BUF_SIZE, RW_PROT_WRITE),
TEST(BUF_SIZE, BUF_SIZE, RW_PROT_EXEC),
TEST(BUF_SIZE, BUF_SIZE - 1, RW_PROT_NONE | RW_PROT_BELOW),
TEST(BUF_SIZE, BUF_SIZE - 1, RW_PROT_READ | RW_PROT_BELOW),
TEST(BUF_SIZE, BUF_SIZE - 1, RW_PROT_WRITE | RW_PROT_BELOW),
TEST(BUF_SIZE, BUF_SIZE - 1, RW_PROT_EXEC | RW_PROT_BELOW),
TEST(BUF_SIZE, BUF_SIZE - 1, RW_PROT_NONE),
TEST(BUF_SIZE, BUF_SIZE - 1, RW_PROT_READ),
TEST(BUF_SIZE, BUF_SIZE - 1, RW_PROT_WRITE),
TEST(BUF_SIZE, BUF_SIZE - 1, RW_PROT_EXEC)
};
for (size_t i = 0; i < sizeof (tcases) / sizeof (tcases[0]); ++i)
test (tcases [i]);
return 0;
}
/***********************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"",
0,
run_test,
"",
(void*)0 /* sentinel */);
}