[cfe-dev] Reporting UBSan issues at compile-time
Anna Zaks via cfe-dev
cfe-dev at lists.llvm.org
Thu Mar 23 10:39:59 PDT 2017
> On Mar 23, 2017, at 8:18 AM, David Blaikie via cfe-dev <cfe-dev at lists.llvm.org> wrote:
>
> FWIW - Clang is fairly allergic to emitting diagnostics based on optimization because they tend to present usability problems. They can appear/disappear due to seemingly unrelated changes in the code (that trigger or hinder optimizations that cause the diagnostic path to be hit).
>
> Usually the idea is to implement these sort of bug finding techniques in Clang's static analyzer. So perhaps there would be a way to feed UBSan’s facts/checks into the static analyzer in a more consistent way (I'm sure some of the same checks are implemented there already - but generalizing/unifying UBSan's checks to feed into the static analyzer could be handy).
>
+ 1
We already have several tools that detect errors, mainly UB, statically. Depending on the type of analysis you choose to write and false positive tolerance I’d suggest extending one of these:
- compiler warnings
- clang-tidy
- clang static analyzer
I believe it will be trivial to teach the clang static analyzer to catch the bug in the example you provide below.
Cheers,
Anna
> - Dave
>
> On Wed, Mar 22, 2017 at 6:52 PM Vedant Kumar via cfe-dev <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
> Hi,
>
> I've performed some experiments with reporting UBSan diagnostics at
> compile-time and think that this is a useful thing to do. I'd like to discuss
> the motivation, the approach I took, and some results.
>
> === Motivation ===
>
> We're interested in fixing UB in our projects and use UBSan to do this.
> However, we have lots of software that is easy to build but hard to run, or
> hard to test with adequate code coverage (e.g firmware). This limits the amount
> of bugs we can catch with UBSan.
>
> It would be nice if we could report UB at compile-time without false positives.
> We wouldn't be able to report everything a runtime tool could, but we would be
> able to report a large number of real bugs very quickly, just by rebuilding all
> our software with a flag enabled.
>
> === Approach ===
>
> I wrote a simple analysis which detects UB statically by piggybacking off UBSan.
> It's actually able to issue decent diagnostics. It only issues a diagnostic if
> it finds a call to a UBSan diagnostic handler which post-dominates the function
> entry block.
>
> The idea is: if a function unconditionally exhibits UB when called, it's worth
> reporting the UB at compile-time.
>
> Here is a full example. This C program has UB because it returns a null pointer
> when it shouldn't:
>
> ```
> __attribute__((returns_nonnull)) int *returns_nonnull(int *p) {
> return p; // Bug: null pointer returned here.
> }
>
> int main() {
> returns_nonnull((int *)0LL);
> return 0;
> }
> ```
>
> With UBSan enabled, here's the IR we get:
>
> ```
> define nonnull i32* @returns_nonnull(i32* %p) #0 {
> entry:
> ...
> %1 = icmp ne i32* %p, null, !nosanitize !2
> br i1 %1, label %cont, label %handler.nonnull_return
>
> handler.nonnull_return:
> call void @__ubsan_handle_nonnull_return(...), !nosanitize !2
> br label %cont, !nosanitize !2
>
> cont:
> ret i32* %p
> }
>
> define i32 @main() #0 {
> entry:
> ...
> %call = call nonnull i32* @returns_nonnull(i32* null)
> ret i32 0
> }
> ```
>
> At -O2, LLVM inlines @returns_nonnull and throws away the null check:
>
> ```
> define i32 @main() local_unnamed_addr #0 {
> entry:
> tail call void @__ubsan_handle_nonnull_return(...), !nosanitize !2
> ret i32 0
> }
> ```
>
> The call to UBSan's diagnostic handler post-dominates the function entry block,
> so we report it right away:
>
> $ clang -fsanitize=undefined -O2 -Xclang -enable-llvm-linter buggy.c
> Undefined behavior: invalid null return value (buggy.c:3:1)
>
> === Results ===
>
> I packaged up my analysis into LLVM's Lint pass and added a clang option to
> enable linting. The initial patch is up for review:
>
> https://reviews.llvm.org/D30949 <https://reviews.llvm.org/D30949> - Add an option to enable LLVM IR linting
>
> I built a few internal projects with UBSan, optimizations, and linting enabled.
> This exposed real bugs. The only problem was that I got reports about UB in
> dead code. Maybe this can be addressed by setting up sanitizer blacklists?
>
> === Alternatives? ===
>
> We could try implementing something like the STACK UB checker:
>
> https://people.csail.mit.edu/nickolai/papers/wang-stack-tocs.pdf <https://people.csail.mit.edu/nickolai/papers/wang-stack-tocs.pdf>
>
> I haven't compared my approach vs. STACK in terms of bug-finding efficacy. The
> latter does seem harder to implement.
>
> I'm interested in hearing what others think.
>
> thanks,
> vedant
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170323/711935df/attachment.html>
More information about the cfe-dev
mailing list