From 01e843722aa39b3411d349c6fbea80ad87a6e9ef Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 5 Mar 2015 18:48:14 +0100 Subject: erts: Reject duplicate keys for hamt in binary_to_term --- erts/emulator/beam/beam_emu.c | 2 +- erts/emulator/beam/erl_map.c | 23 ++++++++++++++--------- erts/emulator/beam/erl_map.h | 2 +- erts/emulator/beam/external.c | 4 ++-- 4 files changed, 18 insertions(+), 13 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 9b4cd38d69..d45aa93f73 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -6589,7 +6589,7 @@ new_map(Process* p, Eterm* reg, BeamInstr* I) p->htop = mhp; factory.p = p; - return erts_hashmap_from_array(&factory, thp, n/2); + return erts_hashmap_from_array(&factory, thp, n/2, 0); } if (HeapWordsLeft(p) < need) { diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c index eacdd0b6c3..3ccfc61b08 100644 --- a/erts/emulator/beam/erl_map.c +++ b/erts/emulator/beam/erl_map.c @@ -87,7 +87,7 @@ static Eterm hashmap_values(Process *p, Eterm map); static Eterm hashmap_delete(Process *p, Uint32 hx, Eterm key, Eterm node); static Eterm map_from_validated_list(Process *p, Eterm list, Uint size); static Eterm hashmap_from_validated_list(Process *p, Eterm list, Uint size); -static Eterm hashmap_from_unsorted_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n); +static Eterm hashmap_from_unsorted_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, int reject_dupkeys); static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, int is_root); static Eterm hashmap_from_chunked_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, int is_root); static Eterm hashmap_info(Process *p, Eterm node); @@ -419,7 +419,7 @@ static Eterm hashmap_from_validated_list(Process *p, Eterm list, Uint size) { } factory.p = p; - res = hashmap_from_unsorted_array(&factory, hxns, size); + res = hashmap_from_unsorted_array(&factory, hxns, size, 0); erts_free(ERTS_ALC_T_TMP, (void *) hxns); ERTS_VERIFY_UNUSED_TEMP_ALLOC(p); @@ -462,7 +462,8 @@ static Eterm hashmap_from_validated_list(Process *p, Eterm list, Uint size) { return res; } -Eterm erts_hashmap_from_array(ErtsHeapFactory* factory, Eterm *leafs, Uint n) { +Eterm erts_hashmap_from_array(ErtsHeapFactory* factory, Eterm *leafs, Uint n, + int reject_dupkeys) { Uint32 sw, hx; Uint ix; hxnode_t *hxns; @@ -481,7 +482,7 @@ Eterm erts_hashmap_from_array(ErtsHeapFactory* factory, Eterm *leafs, Uint n) { leafs += 2; } - res = hashmap_from_unsorted_array(factory, hxns, n); + res = hashmap_from_unsorted_array(factory, hxns, n, reject_dupkeys); erts_free(ERTS_ALC_T_TMP, (void *) hxns); @@ -523,7 +524,7 @@ Eterm erts_hashmap_from_ks_and_vs_extra(Process *p, Eterm *ks, Eterm *vs, Uint n } factory.p = p; - res = hashmap_from_unsorted_array(&factory, hxns, sz); + res = hashmap_from_unsorted_array(&factory, hxns, sz, 0); erts_free(ERTS_ALC_T_TMP, (void *) hxns); ERTS_VERIFY_UNUSED_TEMP_ALLOC(p); @@ -532,7 +533,8 @@ Eterm erts_hashmap_from_ks_and_vs_extra(Process *p, Eterm *ks, Eterm *vs, Uint n } static Eterm hashmap_from_unsorted_array(ErtsHeapFactory* factory, - hxnode_t *hxns, Uint n) { + hxnode_t *hxns, Uint n, + int reject_dupkeys) { Uint jx = 0, ix = 0, lx, cx; Eterm res; @@ -566,7 +568,10 @@ static Eterm hashmap_from_unsorted_array(ErtsHeapFactory* factory, while(ix < jx) { lx = ix; while(ix < jx && EQ(CAR(list_val(hxns[ix].val)), CAR(list_val(hxns[lx].val)))) { - if (hxns[ix].i > hxns[lx].i) { + if (reject_dupkeys) + return THE_NON_VALUE; + + if (hxns[ix].i > hxns[lx].i) { lx = ix; } ix++; @@ -1030,7 +1035,7 @@ static Eterm map_merge(Process *p, Eterm nodeA, Eterm nodeB) { } factory.p = p; - res = hashmap_from_unsorted_array(&factory, hxns, n); + res = hashmap_from_unsorted_array(&factory, hxns, n, 0); erts_free(ERTS_ALC_T_TMP, (void *) hxns); ERTS_VERIFY_UNUSED_TEMP_ALLOC(p); @@ -1076,7 +1081,7 @@ static Eterm map_merge_mixed(Process *p, Eterm flat, Eterm tree, int swap_args) } factory.p = p; - res = hashmap_from_unsorted_array(&factory, hxns, n); + res = hashmap_from_unsorted_array(&factory, hxns, n, 0); erts_free(ERTS_ALC_T_TMP, (void *) hxns); ERTS_VERIFY_UNUSED_TEMP_ALLOC(p); diff --git a/erts/emulator/beam/erl_map.h b/erts/emulator/beam/erl_map.h index 35dbed86a9..39d98b9e03 100644 --- a/erts/emulator/beam/erl_map.h +++ b/erts/emulator/beam/erl_map.h @@ -102,7 +102,7 @@ int erts_validate_and_sort_map(map_t* map); void hashmap_iterator_init(struct ErtsWStack_* s, Eterm node); Eterm* hashmap_iterator_next(struct ErtsWStack_* s); int hashmap_key_hash_cmp(Eterm* ap, Eterm* bp); -Eterm erts_hashmap_from_array(ErtsHeapFactory*, Eterm *leafs, Uint n); +Eterm erts_hashmap_from_array(ErtsHeapFactory*, Eterm *leafs, Uint n, int reject_dupkeys); const Eterm *erts_hashmap_get(Uint32 hx, Eterm key, Eterm map); #define erts_hashmap_from_ks_and_vs(P, KS, VS, N) \ diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index 0e012e9eec..9bcd9a7a50 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -3910,10 +3910,10 @@ dec_term_atom_common: next = (Eterm *) hamt_list->next; objp = hamt_list->objp; - /*SVERK Make it reject duplicate keys */ *objp = erts_hashmap_from_array(&factory, hamt_list->leaf_array, - hamt_list->size); + hamt_list->size, + 1); if (is_non_value(*objp)) goto error; -- cgit v1.2.3