Package not found: Java:packages/mathjax

File 0916-ets-Treat-keys-containing-maps-as-unbound.patch of Package erlang

From eb7e92f0b42e9f6a6617962b00f9015e22cadadb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Tue, 16 Apr 2024 15:27:39 +0200
Subject: [PATCH] ets: Treat keys containing maps as unbound

Fixes #8385
---
 erts/emulator/beam/erl_db_hash.c |  2 +-
 erts/emulator/beam/erl_db_tree.c |  2 +-
 erts/emulator/beam/erl_db_util.c | 29 ++++++++++-------------------
 erts/emulator/beam/erl_db_util.h |  2 +-
 lib/stdlib/test/ets_SUITE.erl    | 16 +++++++++++++++-
 5 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index 6eb7bde1b4..a5e6167785 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -2943,7 +2943,7 @@ static int analyze_pattern(DbTableHash *tb, Eterm pattern,
 	} else {
 	    key = db_getkey(tb->common.keypos, tpl);
 	    if (is_value(key)) {
-		if (!db_has_variable(key)) {   /* Bound key */
+		if (db_is_fully_bound(key)) {
 		    int ix, search_slot;
 		    HashDbTerm** bp;
 		    erts_rwmtx_t* lck;
diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c
index a439b974a7..8329764cf7 100644
--- a/erts/emulator/beam/erl_db_tree.c
+++ b/erts/emulator/beam/erl_db_tree.c
@@ -3749,7 +3749,7 @@ static enum ms_key_boundness key_boundness(DbTableCommon *tb,
     key = db_getkey(tb->keypos, pattern);
     if (is_non_value(key))
 	return MS_KEY_IMPOSSIBLE;  /* can't possibly match anything */
-    if (!db_has_variable(key)) {   /* Bound key */
+    if (db_is_fully_bound(key)) {
         *keyp = key;
 	return MS_KEY_BOUND;
     } else if (key != am_Underscore &&
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 8bace68d0f..7488c5c893 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -3514,11 +3514,8 @@ int db_has_map(Eterm node) {
     return 0;
 }
 
-/* check if obj is (or contains) a variable */
-/* return 1 if obj contains a variable or underscore */
-/* return 0 if obj is fully ground                   */
-
-int db_has_variable(Eterm node) {
+/* Check if obj is fully bound (contains no variables, underscores, or maps) */
+int db_is_fully_bound(Eterm node) {
     DECLARE_ESTACK(s);
 
     ESTACK_PUSH(s,node);
@@ -3539,30 +3536,24 @@ int db_has_variable(Eterm node) {
 		while(arity--) {
 		    ESTACK_PUSH(s,*(++tuple));
 		}
-            } else if (is_flatmap(node)) {
-                Eterm *values = flatmap_get_values(flatmap_val(node));
-                Uint size = flatmap_get_size(flatmap_val(node));
-                ESTACK_PUSH(s, ((flatmap_t *) flatmap_val(node))->keys);
-                while (size--) {
-                    ESTACK_PUSH(s, *(values++));
-                }
-            } else if (is_map(node)) { /* other map-nodes or map-heads */
-                Eterm *ptr = hashmap_val(node);
-                int i = hashmap_bitcount(MAP_HEADER_VAL(*ptr));
-                ptr += MAP_HEADER_ARITY(*ptr);
-                while(i--) { ESTACK_PUSH(s, *++ptr); }
+            } else if (is_map(node)) {
+                /* Like in Erlang code, "literal" maps in a pattern match any
+                 * map that has the given elements, so they must be considered
+                 * variable. */
+                DESTROY_ESTACK(s);
+                return 0;
             }
 	    break;
 	case TAG_PRIMARY_IMMED1:
 	    if (node == am_Underscore || db_is_variable(node) >= 0) {
 		DESTROY_ESTACK(s);
-		return 1;
+		return 0;
 	    }
 	    break;
 	}
     }
     DESTROY_ESTACK(s);
-    return 0;
+    return 1;
 }
 
 /* 
diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h
index 6ed1e15104..eb129aadcd 100644
--- a/erts/emulator/beam/erl_db_util.h
+++ b/erts/emulator/beam/erl_db_util.h
@@ -450,7 +450,7 @@ void* db_store_term_comp(DbTableCommon *tb, /*May be NULL*/
 Eterm db_copy_element_from_ets(DbTableCommon* tb, Process* p, DbTerm* obj,
 			       Uint pos, Eterm** hpp, Uint extra);
 int db_has_map(Eterm obj);
-int db_has_variable(Eterm obj);
+int db_is_fully_bound(Eterm obj);
 int db_is_variable(Eterm obj);
 void db_do_update_element(DbUpdateHandle* handle,
 			  Sint position,
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 588096301d..cd021e78af 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -102,6 +102,7 @@
 -export([whereis_table/1]).
 -export([ms_excessive_nesting/1]).
 -export([error_info/1]).
+-export([bound_maps/1]).
 
 -export([init_per_testcase/2, end_per_testcase/2]).
 %% Convenience for manual testing
@@ -180,7 +181,9 @@ all() ->
      test_delete_table_while_size_snapshot,
      test_decentralized_counters_setting,
      ms_excessive_nesting,
-     error_info].
+     error_info,
+     bound_maps
+    ].
 
 
 groups() ->
@@ -9061,6 +9064,17 @@ ets_apply(F, Args, Opts) ->
 ets_format_args(Args) ->
     lists:join(", ", [io_lib:format("~P", [A,10]) || A <- Args]).
 
+bound_maps(_Config) ->
+    T = ets:new('__bound_maps__', [ordered_set, public]),
+    Ref = make_ref(),
+    Attrs = [#{}, #{key => value}],
+    [ets:insert_new(T, {{Attr, Ref}, original}) || Attr <- Attrs],
+    Attr = #{},
+    Key = {Attr, Ref},
+    MS = [{{Key, '$1'},[],[{{{element, 1, '$_'}, {const, new}}}]}],
+    2 = ets:select_replace(T, MS),
+    ok.
+
 %%%
 %%% Common utility functions.
 %%%
-- 
2.35.3

openSUSE Build Service is sponsored by