Hacker News new | ask | show | jobs
by turndown 726 days ago
I wouldn’t say they explicitly mention ASan, but in general you will see certain well known C++ developers/community members insist that with a set of sanitizers you won’t have to worry about the kind of things safety focused programmers would like added to C++, all the time never mentioning false positives.
1 comments

ASAN is only a probabilistic sanitizer, but adding deterministic checks, like out-of-bounds checks or integer overflow checks, is the same in C/C++ compiled with the appropriate options as what is done in any programming language where these checks are done by default.

In that case there are no false positives or negatives.

Pray tell: what magic C/C++ compiler options do I add to enable deterministic OOB checks that never produce any false positives or negatives?
If you had bothered to search the gcc or clang manual, you would have found e.g. "-fsanitize=bounds-strict".

There is nothing magic about this option. With it C or C++ is compiled exactly like any other programming language where array bounds checking is implicit.

That means that whenever a new value is computed for a pointer or index that will be used to access an array, the value is compared with the bounds associated with that array.

Such a comparison cannot give false positives or negatives, any address is either within bounds or outside bounds.

This is something that is completely independent of the programming language. Out-of-bounds checking has nothing to do with the syntax or with any explicit features of a programming language. It is just a compilation technique, which can be applied or it can be omitted at the compilation of any programming language, regardless whether the language is C or C++ or Ada or Rust.

The only difference is that in better programming language specifications it is required that any conforming compiler must by default insert bounds checks, while in the C and C++ standards the behavior of the compiler is unspecified and the existing compilers have a bad default behavior, so it is the responsibility of the programmer to use the right compiler options.

Weird, the following program compiles and runs without complaint under `-fsanitize=bounds-strict,address,undefined` and outputs the rather fetching output `��1�I��^H��H���PTE1�1�H�Ǧ@`:

    #include <stdio.h>

    int main(int argc, char **argv) {
        printf("%s\n", argv[-8]);
    }
(https://godbolt.org/z/ef8KMGnce - feel free to try other values to dump out environment variables and other stack crap)

Oh, but maybe that's because the compiler has no model of how `argv` works. Fine, try this?

    #include <stdio.h>
    
    int foo(volatile char *x) {
        return x[0] + x[-64];
    }
    
    int main(int argc, char **argv) {
        char x[1] = {42};
        printf("%d\n", foo(x));
    }
(https://godbolt.org/z/TMzehfGah)

Happily loads way out of bounds, no problem whatsoever - no runtime error, no sanitizer complaints, nothing.

Sanitizers are great, but they are not perfect. They are not a replacement for real array bounds checking; other languages that do real bounds checking do so by carrying the bounds with the object which is categorically impossible under the standard C ABIs.

You did not use arrays, so there were no bounds to be checked.

The C language indeed allows the use of pointers having arbitrary values that cannot be checked in any way.

However it is trivial to avoid the use of such pointers and any decent programmer will never use such pointers, because they are never needed.

Unfortunately, it is difficult to forbid the use of such pointers, because there are too many legacy programs.

That however cannot be an excuse for any programmer who is writing a new program. If someone uses pointers in such a way, that cannot happen through an unwilling mistake, so it is their fault and they have no right to blame the programming language.

New programs are unfortunately bound to old APIs. There's not much you can do here to fix the problem.