[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [csmith-dev] checksum for floats



Hi Faraz,

Thanks for bringing this up. When --float is passed, programs generated by Csmith are not supposed to be undefined-behavior-free. The big issue falls into the same category as you mentioned - possible overflow due to converting a large floating-point value to an integer value. I believe there must be some other overflow cases besides the one that you pointed out.

I just pushed a commit trying to fix your particular case. Hopefully it would meet your need and unblock your work at the moment. Thanks.

- Yang


On 2016-10-04 12:07, Faraz Hussain wrote:
Hi,

I am trying to figure out how checksums are being calculated for
floats in a csmith-generated file (wrong1.c).  We found some
unspecified behavior in this program that was due to conversions when
NaN float values are passed (as the first argument) to one of the
transparent_crc() functions.  Here is the relevant part from Section
F.4 of this publicly available draft of the C99 standard
(http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf):

"F.4 Floating to integer conversion
1
If the floating value is infinite or NaN or if the integral part of
the floating value exceeds the range of the integer type, then the
‘‘invalid’’ floating-point exception is raised and the
resulting value is unspecified. Whether conversion of non-integer
floating values whose integral part is within the range of the integer
type raises the ‘‘inexact’’ floating-point exception is
unspecified."

This happens with g_112 (line 701), g_236 (line 742), and g_630 (lin
843), all of which are 3D ARRAYS OF UNIONS of type U1. In each case
the union is accessed as a float and a NaN value causes the issue.

These are the functions being called:

static void
transparent_crc (uint64_t val, char* vname, int flag)
{
    crc32_8bytes(val);
    if (flag) {
        printf("...checksum after hashing %s : %lX\n", vname,
crc32_context ^ 0xFFFFFFFFUL);
    }
}

static void
transparent_crc (uint32_t val, char* vname, int flag)
{
    crc32_8bytes(val);
    if (flag) {
        printf("...checksum after hashing %s : %X\n", vname,
crc32_context ^ 0xFFFFFFFFU);
    }
}

Now, I also found that wrong1.c calls function TRANSPARENT_CRC_BYTES
function for  the following cases:

g_115: variable of type U1 accessed as float (line 710)
g_129: static float  (line 714)
g_443: static float  (line 787)
g_633: variable of type U1 accessed as float (line 854)
g_696: static float (line 859)
g_728: variable of type U1 accessed as float (line 870)

static void
transparent_crc_bytes (char *ptr, int nbytes, char* vname, int flag)
{
    int i;
    for (i=0; i<nbytes; i++) {
        crc32_byte(ptr[i]);
    }
    if (flag) {
        printf("...checksum after hashing %s : %lX\n", vname,
crc32_context ^ 0xFFFFFFFFUL);
    }
}

Here is my hunch (please correct me if I am wrong):

transparent_crc_bytes() is the function that should be called to
include a float variable in the checksum. This is exactly what's
happening for normal float variables, and for normal unions accessed
as floats.

However, and this I think is a bug, when elements of  arrays of unions
are accessed as floats, the wrong function, i.e. transparent_crc() is
being called, instead of transparent_crc_bytes().

I will really appreciate if someone can verify if I have this right.
And if so, which file/files I should modify to correct the problem.

Thanks,
Faraz.