Address issue #142

Also add janet_wrap_number_safe to API.
This commit is contained in:
Calvin Rose 2019-07-12 07:19:29 -05:00
parent 6887dd05f6
commit 894877a0e3
6 changed files with 43 additions and 3 deletions

View File

@ -1,6 +1,15 @@
# Changelog
All notable changes to this project will be documented in this file.
## Unreleased
- Fix bug with Nanbox implementation allowing users to created
custom values of any type with typed array and marshal modules, which
was unsafe.
- Add `janet_wrap_number_safe` to API, for converting numbers to Janets
where the number could be any 64 bit, user provided bit pattern. Certain
NaN values (which a machine will never generate as a result of a floating
point operation) are guarded against and converted to a default NaN value.
## 1.1.0 - 2019-07-08
- Change semantics of `-l` flag to be import rather than dofile.
- Fix compiler regression in top level defs with destructuring.

View File

@ -1070,7 +1070,7 @@ static const uint8_t *unmarshal_one(
#else
memcpy(&u.bytes, data + 1, sizeof(double));
#endif
*out = janet_wrap_number(u.d);
*out = janet_wrap_number_safe(u.d);
janet_v_push(st->lookup, *out);
return data + 9;
}

View File

@ -197,10 +197,10 @@ static Janet ta_getter(void *p, Janet key) {
break;
#endif
case JANET_TARRAY_TYPE_F32:
value = janet_wrap_number(array->as.f32[i]);
value = janet_wrap_number_safe(array->as.f32[i]);
break;
case JANET_TARRAY_TYPE_F64:
value = janet_wrap_number(array->as.f64[i]);
value = janet_wrap_number_safe(array->as.f64[i]);
break;
default:
janet_panicf("cannot get from typed array of type %s",

View File

@ -182,6 +182,12 @@ void janet_memempty(JanetKV *mem, int32_t count) {
#ifdef JANET_NANBOX_64
Janet janet_wrap_number_safe(double d) {
Janet ret;
ret.number = isnan(d) ? (0.0 / 0.0) : d;
return ret;
}
void *janet_nanbox_to_pointer(Janet x) {
x.i64 &= JANET_NANBOX_PAYLOADBITS;
return x.pointer;
@ -222,6 +228,12 @@ Janet janet_wrap_number(double x) {
return ret;
}
Janet janet_wrap_number_safe(double d) {
Janet ret;
double x = isnan(d) ? (0.0 / 0.0) : d;
return janet_wrap_number(x);
}
Janet janet_nanbox32_from_tagi(uint32_t tag, int32_t integer) {
Janet ret;
ret.tagged.type = tag;
@ -243,6 +255,10 @@ double janet_unwrap_number(Janet x) {
#else
Janet janet_wrap_number_safe(double d) {
return janet_wrap_number(d);
}
Janet janet_wrap_nil(void) {
Janet y;
y.type = JANET_NIL;
@ -298,3 +314,4 @@ JANET_WRAP_DEFINE(pointer, void *, JANET_POINTER, pointer)
#undef JANET_WRAP_DEFINE
#endif

View File

@ -1276,6 +1276,7 @@ JANET_API void janet_put(Janet ds, Janet key, Janet value);
JANET_API void janet_putindex(Janet ds, int32_t index, Janet value);
JANET_API uint64_t janet_getflags(const Janet *argv, int32_t n, const char *flags);
#define janet_flag_at(F, I) ((F) & ((1ULL) << (I)))
JANET_API Janet janet_wrap_number_safe(double x);
/* VM functions */
JANET_API int janet_init(void);

View File

@ -113,4 +113,17 @@
(check-table-clone @{:a 123 :b 34 :c :hello : 945 0 1 2 3 4 5} "table/clone 1")
(check-table-clone @{} "table/clone 1")
# Issue #142
(def buffer (tarray/buffer 8))
(def buffer-float64-view (tarray/new :float64 1 1 0 buffer))
(def buffer-uint32-view (tarray/new :uint32 2 1 0 buffer))
(set (buffer-uint32-view 1) 0xfffe9234)
(set (buffer-uint32-view 0) 0x56789abc)
(assert (buffer-float64-view 0) "issue #142 nanbox hijack 1")
(assert (= (type (buffer-float64-view 0)) :number) "issue #142 nanbox hijack 2")
(assert (= (type (unmarshal @"\xC8\xbc\x9axV4\x92\xfe\xff")) :number) "issue #142 nanbox hijack 3")
(end-suite)