From ec59b790c52223ff8c8f3f489005df1b6e4a51b6 Mon Sep 17 00:00:00 2001 From: flaviut Date: Sun, 13 Apr 2014 17:42:52 -0400 Subject: [PATCH] JSON index accesses are bounds checked --- lib/pure/json.nim | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 38cdcc3db1..4d6ecb837b 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -644,13 +644,16 @@ proc `[]`*(node: PJsonNode, name: string, default: PJsonNode = nil): PJsonNode = return item return default -proc `[]`*(node: PJsonNode, index: int, default: PJsonNode = nil): PJsonNode = +proc `[]`*(node: PJsonNode, index: int, default: PJsonNode = nil): PJsonNode {.raises: [EInvalidIndex].}= ## Gets the node at `index` in an Array.If `node` is nil, this returns `result`, - ## which is by default `nil` to allow for chaining. Results are undefined if - ## the index is out of range. + ## which is by default `nil` to allow for chaining. `EInvalidIndex` is raised if `index` + ## is out of bounds if isNil(node): return default assert(node.kind == JArray) + if index < 0 or index >= node.elems.len: + raise newException(EInvalidIndex, + "index " & $index & " is out of range [0, " & $node.elems.len & ")") return node.elems[index] proc hasKey*(node: PJsonNode, key: string): bool = @@ -937,13 +940,29 @@ when isMainModule: raise newException(EInvalidValue, "That line was expected to fail") except EInvalidIndex: echo() - let passthroughTest = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd" }""" + let testJson = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd" }""" # nil passthrough - assert(passthroughTest["doesnt_exist"][1] == nil) - assert(passthroughTest["doesnt_exist"]["anything"] == nil) + assert(testJson["doesnt_exist"][1] == nil) + assert(testJson["doesnt_exist"]["anything"] == nil) # default param - assert(passthroughTest["doesnt_exist",%true].bval) - assert(passthroughTest["doesnt_exist"][1,%true].bval) + assert(testJson["doesnt_exist",%true].bval) + assert(testJson["doesnt_exist"][1,%true].bval) + + # Bounds checking + try: + let a = testJson["a"][9] + assert(false, "EInvalidIndex not thrown") + except EInvalidIndex: + discard + try: + let a = testJson["a"][-1] + assert(false, "EInvalidIndex not thrown") + except EInvalidIndex: + discard + try: + assert(testJson["a"][0].num == 1, "Index doesn't correspond to its value") + except: + assert(false, "EInvalidIndex thrown for valid index") discard """ while true: