checkedc / checkedc-clang

This repo contains a version of clang that is being modified to support Checked C. Checked C is an extension to C that lets programmers write C code that is guaranteed by the compiler to be type-safe.
https://www.checkedc.org
502 stars 74 forks source link

Why is explicit (size_t) casting required on byte_counts(unsigned _)? #545

Open AnnaKornfeldSimpson opened 6 years ago

AnnaKornfeldSimpson commented 6 years ago

In the following code snippet, why am I required to explicitly cast freespace to a size_t when defining the bounds for the args to memcpy? If I do not, it gives me a cannot prove bounds warning where the only difference between expected and inferred bounds is that the expected bounds have a (size_t) cast in front of freespace. freespace is already unsigned, it should be able to implicitly convert to size_t. The same behavior occurs when the length is a uint32_t instead of an unsigned int.

foo(uint8_t *buf : itype(array_ptr<uint8_t>) byte_count(len), const uint8_t *data : itype(array_ptr<uint8_t>) byte_count(len), size_t len) {
    unsigned int freespace = TOTAL - USED;
    if (len >= freespace) {
        array_ptr<uint8_t> midBuffer : byte_count((size_t)freespace) = 
            dynamic_bounds_cast<array_ptr<uint8_t>>(buf, byte_count((size_t)freespace));
        // identical dynamic cast for data to tmpData omitted
        memcpy(midBuffer, tmpData, freespace);
    }
}

Note: This bug definitely occurs on Linux and I'm pretty sure also on Windows. Both should be using 64-bit versions of checkedc-clang.

AnnaKornfeldSimpson commented 6 years ago

Another example. In this case I am not sure whether the size_t to uint32_t is casting down to a smaller numerical type.

bar (   void       *outData    : byte_count(outSize),  // OUT: Output data
    size_t      outSize,                           // IN:  Size of output data in bytes
    const void *inData   : byte_count(inSize),     // IN:  Input data                                            
    size_t      inSize,                            // IN:  Size of input data in bytes
)
{    
    if (outSize < inSize) {
        return INVALID_PARAMETER;
    }
    // TODO: In this function, outsize must exactly == inSize. Dynamic bounds cast needed to shrink
    // Since the length inSize is cast to uint32_t in the next function call, need to explicitly cast the bounds as well. This is a pain.

    _Array_ptr<void> tmpOutData : byte_count((uint32_t)inSize) = _Dynamic_bounds_cast<_Array_ptr<void>>(outData, byte_count((uint32_t)inSize));
    _Array_ptr<void> tmpInData  : byte_count((uint32_t)inSize) = _Dynamic_bounds_cast<_Array_ptr<void>>(inData, byte_count((uint32_t)inSize));

   OpOn32BitLens(tmpInData, tmpOutData, (uint32_t)inSize);
}
sulekhark commented 3 years ago

This issue got automatically closed by mistake: GitHub closed issue number N in the checkedc-clang repository when a 3C PR that has a comment "Fixes issue N" (where N refers to the issue number in CCI's repository), was merged to master branch in the checkedc-clang repository. Reopening it.