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

View File

@ -71,13 +71,21 @@ type
current_justified_checkpoint*: Checkpoint current_justified_checkpoint*: Checkpoint
finalized_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 # 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 # that the SSZ serialization can read and write directly from an object with
# only mutable portions of BeaconState into a full BeaconState without using # only mutable portions of BeaconState into a full BeaconState without using
# any extra copies. # extra copies.
doAssert sizeof(Validator) == sizeof(ValidatorStatus) static:
doAssert sizeof(BeaconState) == sizeof(BeaconStateNoImmutableValidators) doAssert sizeof(T) == sizeof(U)
doAssert getSizeofSig(T()) == getSizeofSig(U())
cast[ref T](addr x)[]
proc loadImmutableValidators*(dbSeq: var auto): seq[ImmutableValidatorData] = proc loadImmutableValidators*(dbSeq: var auto): seq[ImmutableValidatorData] =
for i in 0 ..< dbSeq.len: for i in 0 ..< dbSeq.len: