From 894877a0e378595ba7686e40d52e046649d52389 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 12 Jul 2019 07:19:29 -0500 Subject: [PATCH] Address issue #142 Also add janet_wrap_number_safe to API. --- CHANGELOG.md | 9 +++++++++ src/core/marsh.c | 2 +- src/core/typedarray.c | 4 ++-- src/core/wrap.c | 17 +++++++++++++++++ src/include/janet.h | 1 + test/suite7.janet | 13 +++++++++++++ 6 files changed, 43 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7b36744..9c843e3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. diff --git a/src/core/marsh.c b/src/core/marsh.c index 8f5e0bba..dde8fa94 100644 --- a/src/core/marsh.c +++ b/src/core/marsh.c @@ -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; } diff --git a/src/core/typedarray.c b/src/core/typedarray.c index 91bdd92b..586ab36b 100644 --- a/src/core/typedarray.c +++ b/src/core/typedarray.c @@ -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", diff --git a/src/core/wrap.c b/src/core/wrap.c index 746d0792..56bfe813 100644 --- a/src/core/wrap.c +++ b/src/core/wrap.c @@ -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 + diff --git a/src/include/janet.h b/src/include/janet.h index 8ce39b4b..ee486a05 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -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); diff --git a/test/suite7.janet b/test/suite7.janet index 5c2146a7..bebd2ffa 100644 --- a/test/suite7.janet +++ b/test/suite7.janet @@ -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)