File 0225-ets-insert-list-Fix-potential-false-positive-assert-.patch of Package erlang
From d81f3f0c39a89d3560e79ba7d9c6ae6d7585f211 Mon Sep 17 00:00:00 2001
From: Kjell Winblad <kjellwinblad@gmail.com>
Date: Wed, 28 Apr 2021 15:53:45 +0200
Subject: [PATCH] ets:insert(list): Fix potential false-positive assert crash
The YCF extra context obtained by YCF_GET_EXTRA_CONTEXT() could change
between yields as the context is stack allocated before the first
yield. This could lead to a crash in debug builds as there is debug
code that checks that the data that is saved when yielding does not
contain pointers to the stack.
---
erts/emulator/beam/erl_db.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index c23f38a4a5..06cf04f9ee 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -1699,7 +1699,6 @@ static void ets_insert_2_list_lock_tbl(Eterm table_id,
{
BIF_RETTYPE fail_ret;
DbTable* tb;
- ets_insert_2_list_info *ctx;
do {
fail_ret = db_get_table_or_fail_return(&tb,
table_id,
@@ -1707,16 +1706,29 @@ static void ets_insert_2_list_lock_tbl(Eterm table_id,
LCK_WRITE,
bif_ix,
p);
- ctx = YCF_GET_EXTRA_CONTEXT();
if (tb == NULL) {
+ ets_insert_2_list_info *ctx = YCF_GET_EXTRA_CONTEXT();
if (p->freason == TRAP) {
ctx->status = ETS_INSERT_2_LIST_FAILED_TO_GET_LOCK;
} else {
ctx->status = ETS_INSERT_2_LIST_FAILED_TO_GET_LOCK_DESTROY;
ctx->destroy_return_value = fail_ret;
}
+#ifdef DEBUG
+ /*
+ * Setting ctx to NULL to avoid that YCF crashes with a
+ * pointer to stack error when running a debug
+ * build. YCF_GET_EXTRA_CONTEXT() may change between
+ * yields as we use stack allocated data for the context
+ * before the first yield so it is important that the
+ * context is obtained again with YCF_GET_EXTRA_CONTEXT()
+ * if a yield might have happened.
+ */
+ ctx = NULL;
+#endif
YCF_YIELD();
} else {
+ ets_insert_2_list_info *ctx = YCF_GET_EXTRA_CONTEXT();
ctx->status = on_success_status;
ASSERT(DB_LOCK_FREE(tb) || erts_lc_rwmtx_is_rwlocked(&tb->common.rwlock));
ASSERT(!(tb->common.status & DB_DELETE));
--
2.26.2