add stricter ABI-compatibility checks for punned types (#2434)

* add stricter ABI-compatibility checks for punned types

* enforce type isomorphism for each pair of cast types to eliminate potential safety hole
This commit is contained in:
tersec 2021-03-19 12:30:20 +00:00 committed by GitHub
parent 01fe564e46
commit baa43ae7f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 6 deletions

View File

@ -375,7 +375,7 @@ proc putState*(db: BeaconChainDB, key: Eth2Digest, value: var BeaconState) =
updateImmutableValidators(db, db.immutableValidatorsMem, value.validators)
db.put(
subkey(BeaconStateNoImmutableValidators, key),
cast[ref BeaconStateNoImmutableValidators](addr value)[])
isomorphicCast[BeaconStateNoImmutableValidators](value))
proc putState*(db: BeaconChainDB, value: var BeaconState) =
db.putState(hash_tree_root(value), value)
@ -461,7 +461,7 @@ proc getStateOnlyMutableValidators(
case db.get(
subkey(
BeaconStateNoImmutableValidators, key),
cast[ref BeaconStateNoImmutableValidators](addr output)[])
isomorphicCast[BeaconStateNoImmutableValidators](output))
of GetResult.found:
let numValidators = output.validators.len
doAssert db.immutableValidatorsMem.len >= numValidators

View File

@ -71,13 +71,21 @@ type
current_justified_checkpoint*: Checkpoint
finalized_checkpoint*: Checkpoint
static:
func getSizeofSig(x: auto, n: int = 0): seq[(string, int, int)] =
for name, value in x.fieldPairs:
when value is tuple|object:
result.add getSizeofSig(value, n + 1)
result.add((name, sizeof(value), n))
template isomorphicCast*[T, U](x: var U): T =
# Each of these pairs of types has ABI-compatible memory representations, so
# that the SSZ serialization can read and write directly from an object with
# only mutable portions of BeaconState into a full BeaconState without using
# any extra copies.
doAssert sizeof(Validator) == sizeof(ValidatorStatus)
doAssert sizeof(BeaconState) == sizeof(BeaconStateNoImmutableValidators)
# extra copies.
static:
doAssert sizeof(T) == sizeof(U)
doAssert getSizeofSig(T()) == getSizeofSig(U())
cast[ref T](addr x)[]
proc loadImmutableValidators*(dbSeq: var auto): seq[ImmutableValidatorData] =
for i in 0 ..< dbSeq.len: