Testing nonstandard assumption

Discussion in 'C Programming' started by Hallvard B Furuseth, Jun 29, 2003.

  1. 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 != 8)
    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+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
     
    Hallvard B Furuseth, Jun 29, 2003
    #1
    1. Advertising

  2. 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
     
    Hallvard B Furuseth, Jun 29, 2003
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mirek Fidler
    Replies:
    8
    Views:
    572
    Mirek Fidler
    Jul 3, 2003
  2. Replies:
    3
    Views:
    445
  3. Peteris Krumins

    Assumption

    Peteris Krumins, Jan 10, 2004, in forum: C Programming
    Replies:
    9
    Views:
    526
  4. Christian Seberino
    Replies:
    0
    Views:
    362
    Christian Seberino
    Oct 21, 2003
  5. rodchar

    iframe assumption

    rodchar, Dec 19, 2007, in forum: ASP .Net
    Replies:
    3
    Views:
    303
    rodchar
    Dec 19, 2007
Loading...

Share This Page