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

openSUSE Build Service is sponsored by