summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
authorflaviut <tamasflaviu@gmail.com>2014-04-13 17:42:52 -0400
committerflaviut <tamasflaviu@gmail.com>2014-04-13 17:49:16 -0400
commitec59b790c52223ff8c8f3f489005df1b6e4a51b6 (patch)
tree9e690bdaf921d1f3ddfe920931132905a1b03417 /lib/pure
parent64d3b9a34d0b51a6507a9be7ebd2d6fd25d64977 (diff)
downloadNim-ec59b790c52223ff8c8f3f489005df1b6e4a51b6.tar.gz
JSON index accesses are bounds checked
Diffstat (limited to 'lib/pure')
-rw-r--r--lib/pure/json.nim35
1 files changed, 27 insertions, 8 deletions
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 38cdcc3db..4d6ecb837 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: