correctcomputation / checkedc-clang

This is the primary development repository for 3C, a tool for automatically converting legacy C code to the Checked C extension of C, which aims to enforce spatial memory safety. This repository is a fork of Checked C's.
14 stars 5 forks source link

Work around conditional operator bugs #729

Open kyleheadley opened 2 years ago

kyleheadley commented 2 years ago

The compiler doesn't handle the ? : operator as well as we'd like, for example, from icecast:

client.c:192:34: error: passing 'char *' to parameter of incompatible type '_Nt_array_ptr<const char>'
                                 plain ? "text/plain" : "text/html", "utf-8",
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This has been noted in the microsoft repo. However, their priority is low and they might not get to it in our time frame.

a concrete example is:

void takes_string(_Nt_array_ptr<char> s) {}
void test() {
  takes_string(0 ? "true" : "false");
}

this doesn't compile, but will if you pass a simple string rather than with the operator. (Or it will complain about bounds if test is _Checked).

I've seen this string version in icecast and libarchive, I'll note below if there are any other variants.

john-h-kastner commented 2 years ago

Unfortunately, adding a C-Stlye cast is not sufficient to workaround this error. An _Assume_bounds_cast does work, but we can't cast to bounds(unknown) without a different bounds error.

void takes_string(_Nt_array_ptr<char> s) {}
void test() {
  takes_string(_Assume_bounds_cast<_Nt_array_ptr<char>>(0 ? "true" : "false", count(0)));
}

Regarding other variants: this is currently the only error blocking the libtiff build without -alltypes.

libtiff/tif_getimage.c:2613:13: error: cannot guarantee operand of cast to checked function pointer type '_Ptr<int (TIFFRGBAImage * : itype(_Ptr<TIFFRGBAImage>), uint32 * : itype(_Ptr<uint32>), uint32, uint32)>' (aka '_Ptr<int (struct _TIFFRGBAImage * : itype(_Ptr<TIFFRGBAImage>), unsigned int * : itype(_Ptr<uint32>), unsigned int, unsigned int)>') is a function pointer
        img->get = TIFFIsTiled(img->tif) ? gtTileContig : gtStripContig;
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libtiff/tif_getimage.c:2768:13: error: cannot guarantee operand of cast to checked function pointer type '_Ptr<int (TIFFRGBAImage * : itype(_Ptr<TIFFRGBAImage>), uint32 * : itype(_Ptr<uint32>), uint32, uint32)>' (aka '_Ptr<int (struct _TIFFRGBAImage * : itype(_Ptr<TIFFRGBAImage>), unsigned int * : itype(_Ptr<uint32>), unsigned int, unsigned int)>') is a function pointer
        img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate;
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~