-
Notifications
You must be signed in to change notification settings - Fork 5
3C inserts cast into unwritable inline function body that calls function pointer with itype #423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@john-h-kastner Want me to look at this or do you think you will be faster? Hopefully it's just a matter of adding an |
I tried this and suppressing the cast is indeed just a matter of adding a
|
I was trying to write a minimal regression test for this bug, and I found out that the circumstances that trigger it are narrower than I thought. In fact, I haven't found a way to trigger it at all without 3C thinking that the definition of #include "../bsearch_preproc_test.h" where # 1 "foo.h" 3
const void *global_key;
void bsearch (void (*compar)(const void *));
inline void bsearch (void (*compar)(const void *)) {
(*compar) (global_key);
}
_Itype_for_any(T) void bsearch(void ((*compar)(const void *)) :
itype(_Ptr<void(_Ptr<const T>)>)
); The In fact, I found one place where 3C does something different based on whether code is marked as being in a system header. @john-h-kastner It looks like you added that check in the liberal itypes change (#356); why? Did it mitigate a problem that was later fixed in a better way via canWrite constraints (#391)? I'd guess that from now on, we should be relying on canWrite constraints and should not treat system headers any differently from other unwritable files. Furthermore, I'd think that setting Should I go ahead and submit a PR that removes the system header check? That may leave us without a known way to trigger the cast insertion bug. Should I still submit a PR to skip cast insertion in unwritable files even though I may not know of an example on which it makes a difference? What would be the appropriate regression tests for any of this? Obviously we don't want the bug to come back, but it's a little strange to write a regression test that tries to use the system header flag to trigger different behavior in 3C when we have no intention of 3C checking that flag ever again. |
The liberal itypes change (#356) added code to flag them as not having a body even though they did. This may have been a useful mitigation for certain problems with unwritable files at the time, but it risks causing confusion and violating 3C invariants in the future. From now on, we want to handle all unwritable files (including system headers) via the new canWrite constraints approach. It appears that removing this code will immediately fix one problem with cast insertion that is currently blocking the benchmark tests (#423), so we'll go ahead and make this change even though we don't fully understand the cast insertion problem or how to appropriately regression-test it.
I'm continuing to investigate exactly how the system header check led to the undesired cast insertion. The rabbit hole only gets deeper: it appears there may be additional bugs coming into play into this example, and once those bugs are fixed, it may become clearer whether there is still a reasonable example that can trigger cast insertion in an unwritable file. (Specifically, the system header check is altering the way the itype of |
The liberal itypes change (#356) added code to flag them as not having a body even though they did. This may have been a useful mitigation for certain problems with unwritable files at the time, but it risks causing confusion and violating 3C invariants in the future. From now on, we want to handle all unwritable files (including system headers) via the new canWrite constraints approach. It appears that removing this code will immediately fix one problem with cast insertion that is currently blocking the benchmark tests (#423), so we'll go ahead and make this change even though we don't fully understand the cast insertion problem or how to appropriately regression-test it.
I finally found a way to reproduce the problem that doesn't depend on any of the system header or declaration merging stuff:
#include "../bsearchlike.h"
void f(void ((*g)(int *q)) : itype(_Ptr<void(_Ptr<int>)>)) {
int *p = 0;
(*g)(_Assume_bounds_cast<_Ptr<int>>(p));
} 3C inserts a cast only if it believes the cast is necessary according to Checked C's rules, but apparently 3C doesn't correctly implement the Checked C rules in this case because 3C thinks a cast is needed but it actually isn't (the Checked C compiler accepts So, in what is becoming a theme, if (A) an unwritable file never references a writable file (which 3C might modify), (B) the existing unwritable files pass the Checked C type checker, and (C) 3C's cast insertion logic perfectly matches the Checked C type checker's logic, then 3C should never determine that an existing unwritable file needs any more casts inserted. But if any of these conditions fails ((C) in the example above), then we get an unwritable change. AFAIK, none of our real-world code currently violates condition (C) on the 3C main branch, so we can hold off a bit on addressing this issue, but once #433 is fixed, I believe the original
Opinions? |
Uh oh!
There was an error while loading. Please reload this page.
Running
3c stdlib_checked.h -- -O2
gives an errorThis error is currently affecting the benchmark programs tested in our actions repository.
-O2
makesgcc
set__USE_EXTERN_INLINES
which causes the definition forbsearch
to be inlined in thestdlib.h
. 3C then tries to insert a cast in the definition which triggers the unwritable change error.The example below demonstrates the same error.
The text was updated successfully, but these errors were encountered: