Add 'checkedEnumAssign' for validating tainted enum inputs
This commit is contained in:
parent
11aeb996ab
commit
152eb1b58c
|
@ -1,3 +1,6 @@
|
|||
import
|
||||
macros
|
||||
|
||||
template init*(lvalue: var auto) =
|
||||
mixin init
|
||||
lvalue = init(type(lvalue))
|
||||
|
@ -36,9 +39,9 @@ func declval*(T: type): T {.compileTime.} =
|
|||
## ```
|
||||
##
|
||||
## Please note that `declval` has two advantages over `default`:
|
||||
##
|
||||
##
|
||||
## 1. It can return expressions with proper `var` or `lent` types.
|
||||
##
|
||||
##
|
||||
## 2. It will work for types that lack a valid default value due
|
||||
## to `not nil` or `requiresInit` requirements.
|
||||
##
|
||||
|
@ -64,3 +67,43 @@ proc baseType*(obj: RootObj): cstring =
|
|||
proc baseType*(obj: ref RootObj): cstring =
|
||||
obj[].baseType
|
||||
|
||||
when false:
|
||||
# TODO: Implementing this doesn't seem possible at the moment.
|
||||
#
|
||||
# When given enum like:
|
||||
#
|
||||
# type WithoutHoles2 = enum
|
||||
# A2 = 2, B2 = 3, C2 = 4
|
||||
#
|
||||
# ...the code below will print:
|
||||
#
|
||||
# EnumTy
|
||||
# Empty
|
||||
# Sym "A2"
|
||||
# Sym "B2"
|
||||
# Sym "C2"
|
||||
#
|
||||
macro hasHoles*(T: type[enum]): bool =
|
||||
let t = getType(T)[1]
|
||||
echo t.treeRepr
|
||||
return newLit(true)
|
||||
|
||||
func checkedEnumAssign*[E: enum, I: SomeInteger](res: var E, value: I): bool =
|
||||
## This function can be used to safely assign a tainted integer value (coming
|
||||
## from untrusted source) to an enum variable. The function will return `true`
|
||||
## if the integer value is within the acceped values of the enum and `false`
|
||||
## otherwise.
|
||||
|
||||
# TODO: Enums with holes are not supported yet
|
||||
# static: doAssert(not hasHoles(E))
|
||||
|
||||
when I is SomeSignedInt or low(E).int > 0:
|
||||
if value < I(low(E)):
|
||||
return false
|
||||
|
||||
if value > I(high(E)):
|
||||
return false
|
||||
|
||||
res = E value
|
||||
return true
|
||||
|
||||
|
|
|
@ -70,3 +70,65 @@ suite "Objects":
|
|||
T6 is DistinctBar
|
||||
T6 isnot Bar
|
||||
|
||||
when false:
|
||||
# TODO: Not possible yet (see objects.nim)
|
||||
test "hasHoles":
|
||||
type
|
||||
WithoutHoles = enum
|
||||
A1, B1, C1
|
||||
|
||||
WithoutHoles2 = enum
|
||||
A2 = 2, B2 = 3, C2 = 4
|
||||
|
||||
WithHoles = enum
|
||||
A3, B3 = 2, C3
|
||||
|
||||
check:
|
||||
hasHoles(WithoutHoles2) == false
|
||||
hasHoles(WithoutHoles) == false
|
||||
hasHoles(WithHoles) == true
|
||||
|
||||
test "checkedEnumAssign":
|
||||
type
|
||||
SomeEnum = enum
|
||||
A1, B1, C1
|
||||
|
||||
AnotherEnum = enum
|
||||
A2 = 2, B2, C2
|
||||
|
||||
var
|
||||
e1 = A1
|
||||
e2 = A2
|
||||
|
||||
check:
|
||||
checkedEnumAssign(e1, 2)
|
||||
e1 == C1
|
||||
|
||||
check:
|
||||
not checkedEnumAssign(e1, 5)
|
||||
e1 == C1
|
||||
|
||||
check:
|
||||
checkedEnumAssign(e1, 0)
|
||||
e1 == A1
|
||||
|
||||
check:
|
||||
not checkedEnumAssign(e1, -1)
|
||||
e1 == A1
|
||||
|
||||
check:
|
||||
checkedEnumAssign(e2, 2)
|
||||
e2 == A2
|
||||
|
||||
check:
|
||||
not checkedEnumAssign(e2, 5)
|
||||
e2 == A2
|
||||
|
||||
check:
|
||||
checkedEnumAssign(e2, 4)
|
||||
e2 == C2
|
||||
|
||||
check:
|
||||
not checkedEnumAssign(e2, 1)
|
||||
e2 == C2
|
||||
|
||||
|
|
Loading…
Reference in New Issue