Merge pull request #239 from DRMacIver/overflows
Avoid undefined behaviour with large array indices
This commit is contained in:
commit
f147b7fae5
4 files changed
+38
-7
No files matched your search
@@ -5,6 +5,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "jv_alloc.h"
|
#include "jv_alloc.h"
|
||||||
#include "jv.h"
|
#include "jv.h"
|
||||||
@@ -140,6 +141,17 @@ double jv_number_value(jv j) {
|
|||||||
return j.u.number;
|
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)
|
* Arrays (internal helpers)
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ jv jv_bool(int);
|
|||||||
|
|
||||||
jv jv_number(double);
|
jv jv_number(double);
|
||||||
double jv_number_value(jv);
|
double jv_number_value(jv);
|
||||||
|
int jv_is_integer(jv);
|
||||||
|
|
||||||
jv jv_array(void);
|
jv jv_array(void);
|
||||||
jv jv_array_sized(int);
|
jv jv_array_sized(int);
|
||||||
|
|||||||
@@ -26,13 +26,18 @@ static int parse_slice(jv j, jv slice, int* pstart, int* pend) {
|
|||||||
jv_free(end_jv);
|
jv_free(end_jv);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
int start = (int)jv_number_value(start_jv);
|
double dstart = jv_number_value(start_jv);
|
||||||
int end = (int)jv_number_value(end_jv);
|
double dend = jv_number_value(end_jv);
|
||||||
if (start < 0) start = len + start;
|
if (dstart < 0) dstart += len;
|
||||||
if (end < 0) end = len + end;
|
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 > len) end = len;
|
||||||
if (end < start) end = start;
|
if (end < start) end = start;
|
||||||
assert(0 <= start && start <= end && end <= len);
|
assert(0 <= start && start <= end && end <= len);
|
||||||
@@ -51,12 +56,17 @@ jv jv_get(jv t, jv k) {
|
|||||||
v = jv_null();
|
v = jv_null();
|
||||||
}
|
}
|
||||||
} else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) {
|
} else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) {
|
||||||
// FIXME: don't do lookup for noninteger index
|
if(jv_is_integer(k)){
|
||||||
v = jv_array_get(t, (int)jv_number_value(k));
|
v = jv_array_get(t, (int)jv_number_value(k));
|
||||||
if (!jv_is_valid(v)) {
|
if (!jv_is_valid(v)) {
|
||||||
jv_free(v);
|
jv_free(v);
|
||||||
v = jv_null();
|
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) {
|
} else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_OBJECT) {
|
||||||
int start, end;
|
int start, end;
|
||||||
if (parse_slice(t, k, &start, &end)) {
|
if (parse_slice(t, k, &start, &end)) {
|
||||||
|
|||||||
@@ -722,3 +722,11 @@ map(has(2))
|
|||||||
keys
|
keys
|
||||||
[42,3,35]
|
[42,3,35]
|
||||||
[0,1,2]
|
[0,1,2]
|
||||||
|
|
||||||
|
[][.]
|
||||||
|
1000000000000000000
|
||||||
|
null
|
||||||
|
|
||||||
|
map([1,2][0:.])
|
||||||
|
[-1, 1, 2, 3, 1000000000000000000]
|
||||||
|
[[1], [1], [1,2], [1,2], [1,2]]
|
||||||
Reference in new issue
Block a user