[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 14 Apr 2011 19:59:33 +0200
From: Luka Marčetić <paxcoder@...il.com>
To: musl@...ts.openwall.com
Subject: Re: Simple testing task - string functions
Hello again.
Attached is the solution to the task. The program seems to preform as
expected, but may still need double-checking.
The tests therein fail where expected when linked with various old
versions of musl. Note that although the program is designed to allow
tests to fail gracefully as suggested, this does not happen due to bugs
in function implementations in said old versions that the program
depends on. Rich and Chris have confirmed a bug in 0.7.6 that causes a
segfault in the siglongjmp (longjmp to be exact). I'm still waiting for
confirmation of inability of version 0.7.5 to dispose the same signal to
a specified handler properly.
Thanks.
Luka Marčetić
#include <signal.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <setjmp.h>
/**
** \file depends: sysconf, mmap, mprotect, open, signal, sigsetjmp, siglongjmp, fprintf
** \author Luka Marčetić, 2011
**/
//necessary to detect errors, and resume afterwards:
int next; ///< number of the currently executing test, or greater on failure
sigjmp_buf env; ///< will store the signal mask and stack context/environment
void bridge_sig_jmp(int sig);
void print_result(int done, char *name);
/**
** Tests string/memory functions for invalid memory access
** and for correctnes when handling 'high' vs 'low' bytes.
**
** tests: strchr, strlen, strspn, strcspn, memchr
**/
int main()
{
int i, j, k, fd, tmpi, pg_size=sysconf(_SC_PAGESIZE);
char *tmp, *m;
char low=' ', high=128+low, string[]="\x20\x40\x60\x80\xA0\xC0\xE0";
fd = open("/dev/zero", O_RDWR);
m = mmap(NULL, pg_size*2, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
mprotect(m+pg_size, pg_size, PROT_NONE);
signal(SIGSEGV, bridge_sig_jmp);
next=0;
switch (sigsetjmp(env, 1))
{
case 0:
//strchr:
fprintf(stdout, " strchr\n");
for (i=0; i<pg_size; ++i)
m[i]=low;
for (i=1; i<=8; ++i)
{
m[pg_size-i] = high;
for (j=i; j<=pg_size; ++j)
{
tmp = strchr(&m[pg_size-j], high);
if (tmp != &m[pg_size-i])
bridge_sig_jmp(0);
}
m[pg_size-i] = low;
}
case 1:
print_result(0, "stopping at a 'high' character");
for (i=0; i<pg_size; ++i)
m[i]=high;
for (i=1; i<=8; ++i)
{
m[pg_size-i] = low;
for (j=i; j<=pg_size; ++j)
{
tmp = strchr(&m[pg_size-j], low);
if (tmp != &m[pg_size-i])
bridge_sig_jmp(0);
}
m[pg_size-i] = high;
}
case 2:
print_result(1, "stopping at a 'low' character");
for (i=0; i<pg_size; ++i)
m[i]=128;
for (i=1; i<=8; ++i)
{
m[pg_size-i] = '\0';
for (j=i; j<=pg_size; ++j)
{
tmp = strchr(&m[pg_size-j], low);
if (tmp != NULL)
bridge_sig_jmp(0);
}
m[pg_size-i] = 128;
}
case 3:
print_result(2, "stopping at a '\\0' character");
//strlen:
fprintf(stdout, " strlen\n");
//still filled with 128s
for (i=1; i<=8; ++i)
{
m[pg_size-i] = '\0';
for (j=i; j<=pg_size; ++j)
{
tmpi = strlen(&m[pg_size-j]);
if (tmpi != (pg_size-i)-(pg_size-j))
bridge_sig_jmp(0);
}
m[pg_size-i] = 128;
}
case 4:
print_result(3, "stopping at a '\\0' character");
//memchr:
fprintf(stdout, " memchr\n");
for (i=0; i<pg_size; ++i)
m[i]=low; //128 would cause an error per standard itself
for (i=1; i<=8; ++i)
{
m[pg_size-i] = '\0';
for (j=i; j<=pg_size; ++j)
tmp = memchr(&m[pg_size-j], '\0', pg_size+1);
m[pg_size-i] = low;
}
case 5:
print_result(4, "stopping at a '\\0' character");
//strspn:
fprintf(stdout, " strspn\n");
for (i=0; i<pg_size; ++i)
m[i]=string[i%7]; //'high' and 'low' chars
for (i=1; i<=8; ++i)
{
m[pg_size-i] = '\0';
for (j=i; j<=pg_size; ++j)
{
tmpi = strspn(&m[pg_size-j], string);
if (tmpi != (pg_size-i)-(pg_size-j))
bridge_sig_jmp(0);
}
m[pg_size-i] = string[(pg_size-i)%7];
}
case 6:
print_result(5, "stopping at a character not found in the set");
//strcspn:
fprintf(stdout, " strcspn\n");
//still filled with 'high' and 'low' chars
for (k=0; k<3; ++k)
{
m[pg_size-i] = '\0';
for (j=i; j<=pg_size; ++j)
{
tmpi = strcspn(&m[pg_size-j], "\x21\0\x21\0\0\x22");
if (tmpi != (pg_size-i)-(pg_size-j))
bridge_sig_jmp(0);
}
m[pg_size-i] = string[(pg_size-i)%7];
}
case 7:
print_result(6, "stopping at any character from the set");
break;
}
return 0;
}
/**
** A bridge function to be passed to signal(), to call siglongjmp().
** A call to this function means that the current test has failed.
**/
void bridge_sig_jmp(int sig)
{
++next;///< indication that there was an error (see print_result)
siglongjmp(env, next);
return;
}
/**
** Prints a success/failure message
** \param done number of the last test executed.
** \param name name of the last test executed.
**/
void print_result(int done, char *name)
{
if (next > done)
fprintf (stderr, " %s: Failure\n", name);
else
{
fprintf (stdout, " %s: Success\n", name);
next = done+1;
}
return;
}
Powered by blists - more mailing lists
Powered by Openwall GNU/*/Linux -
Powered by OpenVZ