4 ms·
> Safe languages insert additional machine branches to do things like verify that array accesses are in-bounds. In correct code, those branches are never taken.
by jimmytucson 9mo ago
> Safe languages insert additional machine branches to do things like verify that array accesses are in-bounds. In correct code, those branches are never taken. That means that the machine code cannot be 100% branch tested, which is an important component of SQLite's quality strategy.
Doesn't the language compiler write the code that checks if the array access is in-bounds? Why would you need to test the compiler's code?
- scottlamb 9mo agoThey talk about this here: https://sqlite.org/testing.html#statement_versus_branch_coverage https://sqlite.org/testing.html#statement_versus_branch_cove... ...saying that for a statement `if( a>b && c!=25 ){ d++; }`, they use 100% machine-code branch coverage as a way of determining that they've evaluated this in `a<=b`, `a>b && c==25`, and `a>b && c!=25`. (C/C++) branch coverage tools I've used are less strict, only requiring that takes both if and else paths. One could imagine a better high-level branch coverage tool that achieves this intent without dropping to the machine code level, but I'm not sure it exists today in Rust (or any other language for that matter). There might also be an element of "we don't even trust the compiler to be correct and/or ourselves to not have undefined behavior" here, although they also test explicitly for undefined behavior as mentioned later on the page.
- jimmytucson 9mo agoHmm, so in a language that does automatic bounds checking, the compiler might translate a line of source code like: let val = arr[i] to assembly code like: cmp rdx, rsi ; Compare i (rdx) with length (rsi) jae .Lpanic_label ; Jump if i >= length ; later... .Lpanic_label: call core::panicking::panic_bounds_check Are they saying with "correct code" the line of source code won't be covered? Because the assembly instruction to call panic isn't ever reached?
- scottlamb 9mo agoI think they're saying it's not covered: not only because `call` isn't ever reached but also because they identify `jae` as a branch and see it's always not taken. (If there were no lines in your `; later...` section and the branch were always taken, they'd still identify the `jae` as not covered.) It might be reasonable to redefine their metric as "100% branch coverage except for panics"...if you can reliably determine that `jae .Lpanic_label` is a panic jump. It's obvious to us reading your example of course but I don't know that the compiler guarantees panics always "look like that", and only panics look like that.