File 0636-erts-Fix-enif_make_map-with-dynamic-environment.patch of Package erlang
From dbc0330b4137f1bf699ad197f78efe32d076d7a1 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Thu, 17 Sep 2020 15:19:52 +0200
Subject: [PATCH] erts: Fix enif_make_map* with dynamic environment
causing crash on debug VM, by removing some faulty assertions
assuming a real process context.
---
erts/emulator/beam/erl_map.c | 5 ---
erts/emulator/test/nif_SUITE.erl | 15 ++++++++
erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 38 +++++++++++++++++++
3 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index d3e355183d..e1048f9992 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -2061,10 +2061,7 @@ Eterm erts_hashmap_insert(Process *p, Uint32 hx, Eterm key, Eterm value,
hp = HAlloc(p, size);
res = erts_hashmap_insert_up(hp, key, value, &upsz, &stack);
}
-
DESTROY_ESTACK(stack);
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(p);
- ERTS_HOLE_CHECK(p);
return res;
}
@@ -2602,8 +2599,6 @@ unroll:
HRelease(p, hp_end, hp);
not_found:
DESTROY_ESTACK(stack);
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(p);
- ERTS_HOLE_CHECK(p);
UnUseTmpHeapNoproc(2);
return res;
}
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index 739e6214ec..07701e7aa1 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -492,6 +492,21 @@ maps(Config) when is_list(Config) ->
{1, M2} = make_map_remove_nif(M2, "key3"),
{0, undefined} = make_map_remove_nif(self(), key),
+ M5 = lists:foldl(fun(N, MapIn) ->
+ {1, #{N := value}=MapOut} = make_map_put_nif(MapIn, N, value),
+ MapOut
+ end,
+ #{},
+ lists:seq(1,40)),
+ M6 = lists:foldl(fun(N, MapIn) ->
+ {1, MapOut} = make_map_remove_nif(MapIn, N),
+ ok = maps:get(N, MapOut, ok),
+ MapOut
+ end,
+ M5,
+ lists:seq(1,40)),
+ true = (M6 =:= #{}),
+
ok.
api_macros(doc) -> ["Test macros enif_make_list<N> and enif_make_tuple<N>"];
diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
index f3cab31f33..6e7e593e63 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
@@ -2123,6 +2123,19 @@ static ERL_NIF_TERM make_map_put_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
{
ERL_NIF_TERM map_out = enif_make_atom(env, "undefined");
int ret = enif_make_map_put(env, argv[0], argv[1], argv[2], &map_out);
+
+ /* build same map in dynamic env */
+ ErlNifEnv* dynenv = enif_alloc_env();
+ ERL_NIF_TERM map_out2 = enif_make_atom(env, "undefined");
+ int ret2 = enif_make_map_put(dynenv,
+ enif_make_copy(dynenv, argv[0]),
+ enif_make_copy(dynenv, argv[1]),
+ enif_make_copy(dynenv, argv[2]),
+ &map_out2);
+ if (ret != ret2 || !enif_is_identical(map_out, map_out2))
+ map_out = enif_make_string(env, "dynenv failure", ERL_NIF_LATIN1);
+ enif_free_env(dynenv);
+
return enif_make_tuple2(env, enif_make_int(env,ret), map_out);
}
static ERL_NIF_TERM get_map_value_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -2136,12 +2149,37 @@ static ERL_NIF_TERM make_map_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_
{
ERL_NIF_TERM map_out = enif_make_atom(env, "undefined");
int ret = enif_make_map_update(env, argv[0], argv[1], argv[2], &map_out);
+
+ /* build same map in dynamic env */
+ ErlNifEnv* dynenv = enif_alloc_env();
+ ERL_NIF_TERM map_out2 = enif_make_atom(env, "undefined");
+ int ret2 = enif_make_map_update(dynenv,
+ enif_make_copy(dynenv, argv[0]),
+ enif_make_copy(dynenv, argv[1]),
+ enif_make_copy(dynenv, argv[2]),
+ &map_out2);
+ if (ret != ret2 || !enif_is_identical(map_out, map_out2))
+ map_out = enif_make_string(env, "dynenv failure", ERL_NIF_LATIN1);
+ enif_free_env(dynenv);
+
return enif_make_tuple2(env, enif_make_int(env,ret), map_out);
}
static ERL_NIF_TERM make_map_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM map_out = enif_make_atom(env, "undefined");
int ret = enif_make_map_remove(env, argv[0], argv[1], &map_out);
+
+ /* build same map in dynamic env */
+ ErlNifEnv* dynenv = enif_alloc_env();
+ ERL_NIF_TERM map_out2 = enif_make_atom(env, "undefined");
+ int ret2 = enif_make_map_remove(dynenv,
+ enif_make_copy(dynenv, argv[0]),
+ enif_make_copy(dynenv, argv[1]),
+ &map_out2);
+ if (ret != ret2 || !enif_is_identical(map_out, map_out2))
+ map_out = enif_make_string(env, "dynenv failure", ERL_NIF_LATIN1);
+ enif_free_env(dynenv);
+
return enif_make_tuple2(env, enif_make_int(env,ret), map_out);
}
--
2.26.2