Avoid accidental memory allocations in SSZ

This commit is contained in:
Zahary Karadjov 2020-04-15 04:24:13 +03:00 committed by zah
parent ca49494356
commit 8d639d9bd7
2 changed files with 11 additions and 8 deletions

View File

@ -65,13 +65,16 @@ func fromSszBytes*[N](T: type BitArray[N], bytes: openarray[byte]): T =
raise newException(MalformedSszError, "SSZ bit array overflow") raise newException(MalformedSszError, "SSZ bit array overflow")
copyMem(addr result.bytes[0], unsafeAddr bytes[0], bytes.len) copyMem(addr result.bytes[0], unsafeAddr bytes[0], bytes.len)
proc `[]`[T, U, V](s: openArray[T], x: HSlice[U, V]) {.error:
"Please don't use openarray's [] as it allocates a result sequence".}
func readSszValue*(input: openarray[byte], T: type): T = func readSszValue*(input: openarray[byte], T: type): T =
mixin fromSszBytes, toSszType mixin fromSszBytes, toSszType
type T {.used.} = type(result) type T {.used.} = type(result)
template readOffset(n: int): int {.used.}= template readOffset(n: int): int {.used.}=
int fromSszBytes(uint32, input[n ..< n + offsetSize]) int fromSszBytes(uint32, input.toOpenArray(n, n + offsetSize - 1))
when useListType and result is List: when useListType and result is List:
type ElemType = type result[0] type ElemType = type result[0]
@ -106,7 +109,7 @@ func readSszValue*(input: openarray[byte], T: type): T =
for i in 0 ..< result.len: for i in 0 ..< result.len:
trs "TRYING TO READ LIST ELEM ", i trs "TRYING TO READ LIST ELEM ", i
let offset = i * elemSize let offset = i * elemSize
result[i] = readSszValue(input[offset ..< offset+elemSize], ElemType) result[i] = readSszValue(input.toOpenArray(offset, offset + elemSize - 1), ElemType)
trs "LIST READING COMPLETE" trs "LIST READING COMPLETE"
else: else:
@ -129,10 +132,10 @@ func readSszValue*(input: openarray[byte], T: type): T =
elif nextOffset > input.len: elif nextOffset > input.len:
raise newException(MalformedSszError, "SSZ list element offset points past the end of the input") raise newException(MalformedSszError, "SSZ list element offset points past the end of the input")
else: else:
result[i - 1] = readSszValue(input[offset ..< nextOffset], ElemType) result[i - 1] = readSszValue(input.toOpenArray(offset, nextOffset - 1), ElemType)
offset = nextOffset offset = nextOffset
result[resultLen - 1] = readSszValue(input[offset ..< input.len], ElemType) result[resultLen - 1] = readSszValue(input.toOpenArray(offset, input.len - 1), ElemType)
elif result is SomeInteger|bool|enum|BitArray: elif result is SomeInteger|bool|enum|BitArray:
trs "READING BASIC TYPE ", type(result).name, " input=", input.len trs "READING BASIC TYPE ", type(result).name, " input=", input.len
@ -170,13 +173,13 @@ func readSszValue*(input: openarray[byte], T: type): T =
# TODO The extra type escaping here is a work-around for a Nim issue: # TODO The extra type escaping here is a work-around for a Nim issue:
when type(FieldType) is type(SszType): when type(FieldType) is type(SszType):
trs "READING NATIVE ", fieldName, ": ", name(SszType) trs "READING NATIVE ", fieldName, ": ", name(SszType)
field = readSszValue(input[startOffset ..< endOffset], SszType) field = readSszValue(input.toOpenArray(startOffset, endOffset - 1), SszType)
trs "READING COMPLETE ", fieldName trs "READING COMPLETE ", fieldName
elif useListType and FieldType is List: elif useListType and FieldType is List:
field = readSszValue(input[startOffset ..< endOffset], FieldType) field = readSszValue(input.toOpenArray(startOffset, endOffset - 1), FieldType)
else: else:
trs "READING FOREIGN ", fieldName, ": ", name(SszType) trs "READING FOREIGN ", fieldName, ": ", name(SszType)
field = fromSszBytes(FieldType, input[startOffset ..< endOffset]) field = fromSszBytes(FieldType, input.toOpenArray(startOffset, endOffset - 1))
else: else:
unsupported T unsupported T

@ -1 +1 @@
Subproject commit 2c87f53c03b75da401aae625896721a88c626999 Subproject commit 6ce0472ec0d857bb5a3615574580f631f29a4931