emit fake reads for indexing after every bounds-check - #161857
Conversation
| if is_outermost_index { | ||
| self.read_fake_borrows(block, fake_borrow_temps, source_info) | ||
| } else { | ||
| // Keep all fake borrows we've collected so far alive. If we only emitted fake reads at the | ||
| // end, diverging within an index expression could make them unreachable. This would allow | ||
| // bounds checks to perform out-of-bounds accesses (#161852). | ||
| self.read_fake_borrows(block, fake_borrow_temps, source_info); |
There was a problem hiding this comment.
I think this makes the total number of fake reads quadratic in how much nested slice indexing we do, but hopefully that'd only matter in stress tests? Surprisingly, no MIR building tests needed blessing, so I don't have an example to point to.
There was a problem hiding this comment.
This needs 3 or more nested array/slice indexes, so it's not that surprising that no tests are affected. It definitely doesn't seem likely that there's any real code that's going to have large enough numbers of nested indexes for this to have a significant impact.
|
Like #161581, I'm not fully sure where this falls between lang and types in terms of design responsibility, but I'll start by lang-nominating it alongside that. The ask is equivalent: from a user's perspective, what's the language property we're expressing with fake borrows in indexing expressions? Does this approach fit that, or should we be stricter? |
There was a problem hiding this comment.
The code here looks good. I'll wait for lang to discuss.
The original motivation for the fake borrows here was to make a minimal change to (try to) fix the soundness issue. I considered mimicking the borrows done by the Index trait, but I think that was too restrictive and broke too much code.
To fix #161852, we need fake borrows on indexed-into slice pointers to live through subsequent bounds-checks. This PR does that.
The following is now rejected:
This does not affect locations from which bounds-checks are unreachable. The following was already and is still accepted:
Similar to #161581, I imagine if we want to be stricter about that, we'll either need fake reads at any point we diverge or some other mechanism for keeping fake borrows alive that isn't as sensitive to CFG structure.