Commit e529f28
committed
[BoundsSafety] Optimize BS_CHK_AccessSize for the case element type is 1 byte
Previously for something like
```
T* __bidi_indexable ptr;
ptr[idx];
```
for the upper bound check (when BS_CHK_AccessSize is active) we always checked
1. `&ptr[idx] + sizeof(T)` does not overflow
2. `&ptr[idx] + sizeof(T) <= ptr.upper_bound`
However, for the case `sizeof(T) == 1` we can actually just check
`&ptr[idx] < ptr.upper_bound`
and completely avoid performing the overflow check. This gives us
a code size and runtime overhead win in this particular case.
We can use Z3 to prove the two different bounds checks implementations
are identical when the access size is 1 using the SMT-LIBv2 file shown below:
```
(set-logic QF_BV)
(declare-const cur (_ BitVec 64))
(declare-const upper (_ BitVec 64))
(declare-const access_size (_ BitVec 64))
;;; for inspecting model
(declare-const overflows Bool)
(declare-const cur_plus_access_size (_ BitVec 64))
(define-fun add_overflows ((a (_ BitVec 64)) (b (_ BitVec 64))) Bool
(bvult
(bvadd a b)
a
)
)
;;; Access size is not zero
(assert
(not (= access_size #x0000000000000000))
)
;;; `overflows` is a convenience variable for inspecting the model
(assert
(=
overflows
(add_overflows cur access_size)
)
)
;;; `cur_plus_access_size` is a convenience variable for inspecting the model
(assert
(=
cur_plus_access_size
(bvadd cur access_size)
)
)
;;; Consider the special case with access size of 1
(assert
(= access_size #x0000000000000001)
)
;;;; New upper bound check semantics
(define-fun new_in_bounds () Bool
(and
(not (add_overflows cur access_size))
(bvule
(bvadd cur access_size)
upper
)
)
)
;;;; Old upper bound check semantics
(define-fun old_in_bounds () Bool
(and
(bvult
cur
upper
)
)
)
(assert
(not
(=
new_in_bounds
old_in_bounds
)
)
)
(check-sat); reports unsat
(get-model)
(get-value (old_in_bounds))
(get-value (new_in_bounds))
(get-value (cur_plus_access_size))
(get-value (overflows))
```
rdar://139665133
(cherry picked from commit 84b0262)
Conflicts:
clang/test/BoundsSafety/CodeGen/range-check-optimizations.c1 parent 3c84c55 commit e529f28
File tree
3 files changed
+349
-39
lines changed- clang
- lib/CodeGen
- test/BoundsSafety/CodeGen
3 files changed
+349
-39
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
126 | 126 | | |
127 | 127 | | |
128 | 128 | | |
129 | | - | |
130 | | - | |
131 | | - | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
132 | 132 | | |
133 | 133 | | |
134 | 134 | | |
| |||
151 | 151 | | |
152 | 152 | | |
153 | 153 | | |
154 | | - | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
155 | 161 | | |
156 | 162 | | |
157 | 163 | | |
158 | 164 | | |
159 | 165 | | |
160 | 166 | | |
161 | | - | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
162 | 170 | | |
| 171 | + | |
163 | 172 | | |
164 | 173 | | |
165 | 174 | | |
| |||
0 commit comments