Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Testing nonstandard assumption

Reply
Thread Tools

Testing nonstandard assumption

 
 
Hallvard B Furuseth
Guest
Posts: n/a
 
      06-29-2003
I've written a program which attempts to test for various nonstandard
assumptions which a program package (OpenLDAP) makes. I'd appreciate
advice on how to improve it. (Yes, I know the correct way is to not
make these assumptions, but that's easier said than done.)

The program should crash or return failure if an assumption is false.
Hopefully it will not hang or format the harddisk.

/*
* Try to test for the non-ANSI C assumptions in OpenLDAP:
* two's complement integers,
* at least 4-byte 'int',
* 8-bit 'char',
* 32-bit, no padding bits 'unsigned int' or 'unsigned short',
* ASCII or EBCDIC character set (or a superset of these),
* can cast 'int' to 'void *' and back,
* can cast function pointers to 'void *' and back,
* can meaningfully compare pointers to different malloced blocks.
*/

/* #include "confdefs.h" */
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
# include <malloc.h>
#endif
#ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
# define EXIT_FAILURE 1
#endif

static void
sorry(const char *msg)
{
fprintf(stdout, "%s\n", msg);
exit(EXIT_FAILURE);
}

/*
* Try to guess if !(ptr1 <= ptr2 < ptr1+malloced_size) holds
* when ptr1 and ptr2 are two different malloced pointers.
* Required by slapd/sl_malloc.c.
*/
static void
test_malloc(void)
{
char *p, *q, *a[20];
size_t len, n[20];
int i, j, k, cmp1, cmp2;

/* Make a[] a sorted array of malloced pointers */
for (i = 0, k = 1; k <= 2; k++) {
for (len = k; len < 0x800000ul; len *= 7) {
p = malloc(len);
if (p == NULL)
break;
/* can't use qsort(), it expects ordering comparison */
for (j = i; j && a[j-1] > p; --j) {
a[j] = a[j-1];
n[j] = n[j-1];
}
a[j] = p;
n[j] = len;
i++;
}
}

/* check in various ways that the pointers really are sorted */
for (j = 1; j < i; j++)
for (k = 0; k < j; k++)
if (a[j] <= a[k]
|| a[j] + n[j] < a[k]
|| a[j] <= a[k] + n[k]
|| a[j] + n[j] <= a[k] + n[k])
sorry("Cannot order malloced pointers");
for (j = 0; j < i; j++)
free(a[j]);

/* This test can fail on some more architectures than necessary */
for (i = 0; i < 256; i++) {
/* Make two pointers out of random bit patterns */
for (k = 0; k < (int)sizeof(char *); k++) {
((unsigned char *) &p) [k] = rand();
((unsigned char *) &q) [k] = rand();
}
/* compare them as memory blocks and as pointers */
cmp1 = memcmp(&p, &q, sizeof(char *));
if (cmp1 == 0)
break;
cmp1 = (cmp1 < 0 ? -1 : 1);
if (p < q)
cmp2 = -1;
else if (p > q)
cmp2 = 1;
else
sorry("Maybe not linear address model");
if (i == 0) {
j = (cmp1 != cmp2);
} else if (cmp1 != (j ? -cmp2 : cmp2)) {
sorry("Maybe not linear address model");
}
}
}

int
main(void)
{
int i;
unsigned int u;
char *s;

/* Basic assumptions */
/* Two's complement, 8-bit char, at least 32-bit int */
if (~1 != -2 || ~1L != -2L)
sorry("Not a two's complement machine!");
if (CHAR_BIT !=
sorry("More than 8 bits in a byte!");
if (UINT_MAX < 0xffffffffUL || INT_MAX < 0x7fffffffL)
sorry("Too small int or unsigned int (needs 32 bits).");

/* int or short is 32-bit without padding */
/* Required by back-bdb/dbcache.c:bdb_db_hash() */
if (sizeof(unsigned int) == 4) {
s = "Padding bits in unsigned int";
u = (unsigned int) -1;
} else if (sizeof(unsigned short) == 4) {
s = "Padding bits in unsigned short";
u = (unsigned short) -1;
} else {
sorry("Couldn't find a 4-byte integer type");
}
/* count bits in u, expect 32 */
for (i = 0; u; i++)
u >>= 1;
if ((unsigned)i != 32)
sorry(s);

#ifndef HAVE_EBCDIC
/* Character set is ASCII */
for (i = 0; i < 95; i++)
if ((" !\"#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
"`abcdefghijklmnopqrstuvwxyz{|}~" ) [i] != i+32)
break;
if (i != 95 || '\n' != 10)
sorry("Not an ASCII- or EBCDIC-based character set");
#endif


/* The next tests are not fireproof, but are better than nothing */

/* Can cast function pointer to void* and back */
/* Required at least by some threading stuff */
if ((void (*)(const char *)) (void *) sorry != sorry
|| (void (*)(void)) (void *) test_malloc != test_malloc
|| (void *(*)(size_t)) (void *) malloc != malloc
|| (int (*)(const char *)) (void *) puts != puts
|| sizeof(void *) < sizeof(int (*)(void)))
sorry("Cannot cast function pointers to void* and back");

/* Test pointer comparison of malloced pointers */
/* Required by slapd/sl_malloc */
test_malloc();

puts("OK");
return EXIT_SUCCESS;
}

--
Hallvard
 
Reply With Quote
 
 
 
 
Hallvard B Furuseth
Guest
Posts: n/a
 
      06-29-2003
I wrote:

> (...)
> * can cast 'int' to 'void *' and back,
> (...)


Whoops, that comment should be gone. The program has no such test; I
believe I've exorcized that assumption from OpenLDAP.

--
Hallvard
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
iframe assumption rodchar ASP .Net 3 12-19-2007 03:16 PM
Verifying an assumption around possible problem areas in SSL handshake ljnelson@gmail.com Java 3 06-21-2006 05:40 AM
Importing OE address book from nonstandard location Z Firefox 3 09-03-2005 04:22 PM
Assumption Peteris Krumins C Programming 9 01-10-2004 01:24 PM
[ANN] NTL "Nonstandard Template Library" Mirek Fidler C++ 8 07-03-2003 09:08 PM



Advertisments