Cranelift: x64, aarch64, s390x, riscv64: ensure addresses are I64s. (#5972)

* Cranelift: x64, aarch64, s390x, riscv64: ensure addresses are I64s.

@avanhatt has been looking at our address-mode lowering and found an
example where when feeding an `I32`-typed address into a load or store,
we can violate assumptions and get incorrect codegen.

This should never be reachable in practice, because all producers on
64-bit architectures use 64-bit types for addresses. However, our IR is
insufficiently constrained, and allows loads/stores to `I32` addresses
as well. This is nonsensical on a 64-bit architecture.

Initially I had thought we should tighten either the instruction
definition's accepted types, or the CLIF verifier, to reject this.
However both are target-independent, and we don't want to bake
an assumption of 64-bit-ness into the compiler core. Instead this PR
tightens specific backends' lowerings to rejecct loads/stores of
`I32`-typed addresses.

tl;dr: no security implications as all producers use I64-typed
addresses (and must, for correct operation); but we currently accept
I32-typed addresses too, and this breaks other assumptions.

* Allow R64 as well as I64 types.

* Add an explicit extractor to match 64-bit address types.
This commit is contained in:
Chris Fallin
2023-03-09 11:08:16 -08:00
committed by GitHub
parent f877141668
commit 7f3500a172
6 changed files with 34 additions and 18 deletions

View File

@@ -697,63 +697,63 @@
;;;;; Rules for `uload8`;;;;;;;;;
(rule
(lower (uload8 flags p offset))
(lower (uload8 flags p @ (value_type (ty_addr64 _)) offset))
(gen_load p offset (int_load_op $false 8) flags $I64))
;;;;; Rules for `sload8`;;;;;;;;;
(rule
(lower (sload8 flags p offset))
(lower (sload8 flags p @ (value_type (ty_addr64 _)) offset))
(gen_load p offset (int_load_op $true 8) flags $I64))
;;;;; Rules for `uload16`;;;;;;;;;
(rule
(lower (uload16 flags p offset))
(lower (uload16 flags p @ (value_type (ty_addr64 _)) offset))
(gen_load p offset (int_load_op $false 16) flags $I64))
;;;;; Rules for `iload16`;;;;;;;;;
(rule
(lower (sload16 flags p offset))
(lower (sload16 flags p @ (value_type (ty_addr64 _)) offset))
(gen_load p offset (int_load_op $true 16) flags $I64))
;;;;; Rules for `uload32`;;;;;;;;;
(rule
(lower (uload32 flags p offset))
(lower (uload32 flags p @ (value_type (ty_addr64 _)) offset))
(gen_load p offset (int_load_op $false 32) flags $I64))
;;;;; Rules for `iload16`;;;;;;;;;
(rule
(lower (sload32 flags p offset))
(lower (sload32 flags p @ (value_type (ty_addr64 _)) offset))
(gen_load p offset (int_load_op $true 32) flags $I64))
(rule
(lower (has_type ty (load flags p offset)))
(lower (has_type ty (load flags p @ (value_type (ty_addr64 _)) offset)))
(gen_load p offset (load_op ty) flags ty)
)
;;;; for I128
(rule 1
(lower (has_type $I128 (load flags p offset)))
(lower (has_type $I128 (load flags p @ (value_type (ty_addr64 _)) offset)))
(gen_load_128 p offset flags))
;;;;; Rules for `istore8`;;;;;;;;;
(rule
(lower (istore8 flags x p offset))
(lower (istore8 flags x p @ (value_type (ty_addr64 _)) offset))
(gen_store p offset (StoreOP.Sb) flags x))
;;;;; Rules for `istore16`;;;;;;;;;
(rule
(lower (istore16 flags x p offset))
(lower (istore16 flags x p @ (value_type (ty_addr64 _)) offset))
(gen_store p offset (StoreOP.Sh) flags x))
;;;;; Rules for `istore32`;;;;;;;;;
(rule
(lower (istore32 flags x p offset))
(lower (istore32 flags x p @ (value_type (ty_addr64 _)) offset))
(gen_store p offset (StoreOP.Sw) flags x))
;;;;; Rules for `store`;;;;;;;;;
(rule
(lower (store flags x @ (value_type ty) p offset))
(lower (store flags x @ (value_type ty) p @ (value_type (ty_addr64 _)) offset))
(gen_store p offset (store_op ty) flags x))
;;; special for I128
(rule 1
(lower (store flags x @ (value_type $I128 ) p offset))
(lower (store flags x @ (value_type $I128 ) p @ (value_type (ty_addr64 _)) offset))
(gen_store_128 p offset flags x))
(decl gen_icmp (IntCC ValueRegs ValueRegs Type) Reg)