summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Fedorov <maximfca@gmail.com>2021-05-22 22:32:36 -0700
committerSverker Eriksson <sverker@erlang.org>2021-05-25 11:48:27 +0200
commitddbb46df7afb5d27d4db40bed33e900e18f2e350 (patch)
tree5026892d9ca278d54b4d084fc68dd694080a7c1f
parent2bcd9dca08421c6f961223cebf7b781aaf387a23 (diff)
downloaderlang-ddbb46df7afb5d27d4db40bed33e900e18f2e350.tar.gz
erts: Fix internal hash for external pids/ports
When 64-bit external pid and ports were introduced in OTP-24.0, internal hash function was not adjusted accordingly. This led to a large amount of hash collisions, ultimately making maps:from_list and maps:from_keys to crash the emulator (stack overflow, or assertion in a debug build). Co-authored-by: Sverker Eriksson <sverker@erlang.org>
-rw-r--r--erts/emulator/beam/utils.c12
-rw-r--r--erts/emulator/test/map_SUITE.erl13
-rw-r--r--erts/etc/unix/etp-commands.in12
3 files changed, 23 insertions, 14 deletions
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 7df04420da..9947386efa 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -2343,23 +2343,15 @@ make_internal_hash(Eterm term, Uint32 salt)
case EXTERNAL_PID_SUBTAG: {
ExternalThing* thing = external_thing_ptr(term);
/* See limitation #2 */
- #ifdef ARCH_64
POINTER_HASH(thing->node, HCONST_5);
- UINT32_HASH(thing->data.ui[0], HCONST_5);
- #else
- UINT32_HASH_2(thing->node, thing->data.ui[0], HCONST_5);
- #endif
+ UINT32_HASH_2(thing->data.pid.num, thing->data.pid.ser, HCONST_5);
goto pop_next;
}
case EXTERNAL_PORT_SUBTAG: {
ExternalThing* thing = external_thing_ptr(term);
/* See limitation #2 */
- #ifdef ARCH_64
POINTER_HASH(thing->node, HCONST_6);
- UINT32_HASH(thing->data.ui[0], HCONST_6);
- #else
- UINT32_HASH_2(thing->node, thing->data.ui[0], HCONST_6);
- #endif
+ UINT32_HASH_2(thing->data.ui32[0], thing->data.ui32[1], HCONST_6);
goto pop_next;
}
case FLOAT_SUBTAG:
diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl
index 7ace75cab4..c6302d0239 100644
--- a/erts/emulator/test/map_SUITE.erl
+++ b/erts/emulator/test/map_SUITE.erl
@@ -2966,6 +2966,19 @@ t_erts_internal_hash(_Config) when is_list(_Config) ->
i = maps:get({[0,0,0,0,0,0,0]},M7),
j = maps:get({[0,0,0,0,0,0,0,0]},M7),
k = maps:get({[0,0,0,0,0,0,0,0,0]},M7),
+
+ %% Test that external pids and ports don't introduce hash clash,
+ %% caused by high word being ignored (OTP-17436).
+ maps:from_keys([erts_test_utils:mk_ext_pid({a@a, 17},
+ 1 bsl NumBit,
+ 1 bsl SerBit)
+ || NumBit <- lists:seq(0, 31),
+ SerBit <- lists:seq(0, 31)],
+ 1),
+ maps:from_keys([erts_test_utils:mk_ext_port({a@a, 17}, 1 bsl NumBit)
+ || NumBit <- lists:seq(0, 63)],
+ 1),
+
ok.
t_pdict(_Config) ->
diff --git a/erts/etc/unix/etp-commands.in b/erts/etc/unix/etp-commands.in
index ba35ee7091..620ad2679e 100644
--- a/erts/etc/unix/etp-commands.in
+++ b/erts/etc/unix/etp-commands.in
@@ -866,8 +866,8 @@ define etp-extpid-1
printf "#NotExternalPid<%p>", $etp_extpid_1_p->header
else
## External pid
- set $etp_extpid_1_number = $etp_extpid_1_p->data.ui[0]&0x7fff
- set $etp_extpid_1_serial = ($etp_extpid_1_p->data.ui[0]>>15)&0x1fff
+ set $etp_extpid_1_number = $etp_extpid_1_p->data.ui32[0]
+ set $etp_extpid_1_serial = $etp_extpid_1_p->data.ui32[1]
set $etp_extpid_1_np = $etp_extpid_1_p->node
set $etp_extpid_1_creation = $etp_extpid_1_np->creation
set $etp_extpid_1_dep = $etp_extpid_1_np->dist_entry
@@ -926,7 +926,11 @@ define etp-extport-1
printf "#NotExternalPort<%p>", $etp_extport_1->header
else
## External port
- set $etp_extport_1_number = $etp_extport_1_p->data.ui[0]&0x3ffff
+ if $etp_arch64
+ set $etp_extport_1_number = $etp_extport_1_p->data.port.id
+ else
+ set $etp_extport_1_number = $etp_extport_1_p->data.port.low | (((Uint64)$etp_extport_1_p->data.port.high) << 32)
+ end
set $etp_extport_1_np = $etp_extport_1_p->node
set $etp_extport_1_creation = $etp_extport_1_np->creation
set $etp_extport_1_dep = $etp_extport_1_np->dist_entry
@@ -941,7 +945,7 @@ define etp-extport-1
printf "#Port<%u:", $etp_extport_1_node>>6
end
etp-atom-1 ($etp_extport_1_node)
- printf "/%u.%u>", $etp_extport_1_creation, $etp_extport_1_number
+ printf "/%u.%lu>", $etp_extport_1_creation, $etp_extport_1_number
end
end
end