1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-10 18:59:54 +00:00

Disallow NaN as table/struct key.

Fix bugs and add tests for denormalized tables
and structs.
This commit is contained in:
Calvin Rose 2019-01-28 11:50:33 -05:00
parent c333cbfa55
commit 38a7e4faf1
4 changed files with 23 additions and 13 deletions

View File

@ -165,7 +165,7 @@ dist: build/janet-dist.tar.gz
build/janet-%.tar.gz: $(JANET_TARGET) src/include/janet/janet.h \ build/janet-%.tar.gz: $(JANET_TARGET) src/include/janet/janet.h \
janet.1 LICENSE CONTRIBUTING.md $(JANET_LIBRARY) \ janet.1 LICENSE CONTRIBUTING.md $(JANET_LIBRARY) \
build/doc.html README.md build/doc.html README.md build/janet.c
tar -czvf $@ $^ tar -czvf $@ $^
######################### #########################

View File

@ -73,6 +73,7 @@ void janet_struct_put(JanetKV *st, Janet key, Janet value) {
int32_t i, j, dist; int32_t i, j, dist;
int32_t bounds[4] = {index, cap, 0, index}; int32_t bounds[4] = {index, cap, 0, index};
if (janet_checktype(key, JANET_NIL) || janet_checktype(value, JANET_NIL)) return; if (janet_checktype(key, JANET_NIL) || janet_checktype(value, JANET_NIL)) return;
if (janet_checktype(key, JANET_NUMBER) && isnan(janet_unwrap_number(key))) return;
/* Avoid extra items */ /* Avoid extra items */
if (janet_struct_hash(st) == janet_struct_length(st)) return; if (janet_struct_hash(st) == janet_struct_length(st)) return;
for (dist = 0, j = 0; j < 4; j += 2) for (dist = 0, j = 0; j < 4; j += 2)
@ -120,9 +121,7 @@ void janet_struct_put(JanetKV *st, Janet key, Janet value) {
dist = otherdist; dist = otherdist;
hash = otherhash; hash = otherhash;
} else if (status == 0) { } else if (status == 0) {
/* This should not happen - it means /* A key was added to the struct more than once */
* than a key was added to the struct more than once */
janet_exit("struct double put fail");
return; return;
} }
} }
@ -134,15 +133,8 @@ const JanetKV *janet_struct_end(JanetKV *st) {
/* Error building struct, probably duplicate values. We need to rebuild /* Error building struct, probably duplicate values. We need to rebuild
* the struct using only the values that went in. The second creation should always * the struct using only the values that went in. The second creation should always
* succeed. */ * succeed. */
int32_t i, realCount; JanetKV *newst = janet_struct_begin(janet_struct_hash(st));
JanetKV *newst; for (int32_t i = 0; i < janet_struct_capacity(st); i++) {
realCount = 0;
for (i = 0; i < janet_struct_capacity(st); i++) {
JanetKV *kv = st + i;
realCount += janet_checktype(kv->key, JANET_NIL) ? 1 : 0;
}
newst = janet_struct_begin(realCount);
for (i = 0; i < janet_struct_capacity(st); i++) {
JanetKV *kv = st + i; JanetKV *kv = st + i;
if (!janet_checktype(kv->key, JANET_NIL)) { if (!janet_checktype(kv->key, JANET_NIL)) {
janet_struct_put(newst, kv->key, kv->value); janet_struct_put(newst, kv->key, kv->value);

View File

@ -131,6 +131,7 @@ Janet janet_table_remove(JanetTable *t, Janet key) {
/* Put a value into the object */ /* Put a value into the object */
void janet_table_put(JanetTable *t, Janet key, Janet value) { void janet_table_put(JanetTable *t, Janet key, Janet value) {
if (janet_checktype(key, JANET_NIL)) return; if (janet_checktype(key, JANET_NIL)) return;
if (janet_checktype(key, JANET_NUMBER) && isnan(janet_unwrap_number(key))) return;
if (janet_checktype(value, JANET_NIL)) { if (janet_checktype(value, JANET_NIL)) {
janet_table_remove(t, key); janet_table_remove(t, key);
} else { } else {

View File

@ -283,5 +283,22 @@
(++ i)) (++ i))
(assert (= i 6) "when macro")) (assert (= i 6) "when macro"))
# Denormal tables and structs
(assert (= (length {1 2 nil 3}) 1) "nil key struct literal")
(assert (= (length @{1 2 nil 3}) 1) "nil key table literal")
(assert (= (length (struct 1 2 nil 3)) 1) "nil key struct ctor")
(assert (= (length (table 1 2 nil 3)) 1) "nil key table ctor")
(assert (= (length (struct (/ 0 0) 2 1 3)) 1) "nan key struct ctor")
(assert (= (length (table (/ 0 0) 2 1 3)) 1) "nan key table ctor")
(assert (= (length {1 2 nil 3}) 1) "nan key struct literal")
(assert (= (length @{1 2 nil 3}) 1) "nan key table literal")
(assert (= (length (struct 2 1 3 nil)) 1) "nil value struct ctor")
(assert (= (length (table 2 1 3 nil)) 1) "nil value table ctor")
(assert (= (length {1 2 3 nil}) 1) "nil value struct literal")
(assert (= (length @{1 2 3 nil}) 1) "nil value table literal")
(end-suite) (end-suite)