From 014b45b4a98354291cfc7ede8f90d2da4ca5ff2f Mon Sep 17 00:00:00 2001 From: "David R. MacIver" Date: Tue, 10 Dec 2013 09:17:30 +0000 Subject: [PATCH 1/2] add checking of numeric indices to an array to see if they can reasonably be considered integers. Avoid undefined behaviour if out of bounds --- jv.c | 12 ++++++++++++ jv.h | 1 + jv_aux.c | 13 +++++++++---- tests/all.test | 4 ++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/jv.c b/jv.c index eea6a290..d1ae8d90 100644 --- a/jv.c +++ b/jv.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "jv_alloc.h" #include "jv.h" @@ -140,6 +141,17 @@ double jv_number_value(jv j) { return j.u.number; } +int jv_is_integer(jv j){ + if(jv_get_kind(j) != JV_KIND_NUMBER){ + return 0; + } + double x = jv_number_value(j); + if(x != x || x > INT_MAX || x < INT_MIN){ + return 0; + } + + return x == (int)x; +} /* * Arrays (internal helpers) diff --git a/jv.h b/jv.h index 8d61d104..70024735 100644 --- a/jv.h +++ b/jv.h @@ -60,6 +60,7 @@ jv jv_bool(int); jv jv_number(double); double jv_number_value(jv); +int jv_is_integer(jv); jv jv_array(); jv jv_array_sized(int); diff --git a/jv_aux.c b/jv_aux.c index 76712aee..e994053d 100644 --- a/jv_aux.c +++ b/jv_aux.c @@ -51,10 +51,15 @@ jv jv_get(jv t, jv k) { v = jv_null(); } } else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) { - // FIXME: don't do lookup for noninteger index - v = jv_array_get(t, (int)jv_number_value(k)); - if (!jv_is_valid(v)) { - jv_free(v); + if(jv_is_integer(k)){ + v = jv_array_get(t, (int)jv_number_value(k)); + if (!jv_is_valid(v)) { + jv_free(v); + v = jv_null(); + } + } else { + jv_free(t); + jv_free(k); v = jv_null(); } } else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_OBJECT) { diff --git a/tests/all.test b/tests/all.test index 71918a6f..15e075d4 100644 --- a/tests/all.test +++ b/tests/all.test @@ -718,3 +718,7 @@ map(has(2)) keys [42,3,35] [0,1,2] + +[][.] +1000000000000000000 +null From 5412f3f1c1cade37041c2770ab328c146cf7c74a Mon Sep 17 00:00:00 2001 From: "David R. MacIver" Date: Tue, 10 Dec 2013 09:18:16 +0000 Subject: [PATCH 2/2] convert range bounds to integers in a way that avoids undefined behaviour --- jv_aux.c | 17 +++++++++++------ tests/all.test | 4 ++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/jv_aux.c b/jv_aux.c index e994053d..ec2aaa18 100644 --- a/jv_aux.c +++ b/jv_aux.c @@ -26,13 +26,18 @@ static int parse_slice(jv j, jv slice, int* pstart, int* pend) { jv_free(end_jv); return 0; } else { - int start = (int)jv_number_value(start_jv); - int end = (int)jv_number_value(end_jv); - if (start < 0) start = len + start; - if (end < 0) end = len + end; + double dstart = jv_number_value(start_jv); + double dend = jv_number_value(end_jv); + if (dstart < 0) dstart += len; + if (dend < 0) dend += len; + if (dstart < 0) dstart = 0; + if (dstart > len) dstart = len; + + int start = (int)dstart; + int end = (dend > len) ? len : (int)dend; + // Ends are exclusive but e.g. 1 < 1.5 so :1.5 should be :2 not :1 + if(end < dend) end += 1; - if (start < 0) start = 0; - if (start > len) start = len; if (end > len) end = len; if (end < start) end = start; assert(0 <= start && start <= end && end <= len); diff --git a/tests/all.test b/tests/all.test index 15e075d4..3615bee9 100644 --- a/tests/all.test +++ b/tests/all.test @@ -722,3 +722,7 @@ keys [][.] 1000000000000000000 null + +map([1,2][0:.]) +[-1, 1, 2, 3, 1000000000000000000] +[[1], [1], [1,2], [1,2], [1,2]]