summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Stephani <phst@google.com>2020-07-25 23:04:05 +0200
committerPhilipp Stephani <phst@google.com>2020-07-31 18:18:27 +0200
commit8c94ca94dc2772e5c651de6cf46bfffc388234d5 (patch)
tree2ebdcfd487f06afd5aa3b66102b18b2f3f7cd9ac
parent8ecca2f09f6bc387412f258c4fc4e3ddf807b2b3 (diff)
downloademacs-8c94ca94dc2772e5c651de6cf46bfffc388234d5.tar.gz
Backport: Fix subtle bug when checking liveness of module values.
We can't simply look up the Lisp object in the global reference table because an invalid local and a valid global reference might refer to the same object. Instead, we have to test the address of the global reference against the stored references. * src/emacs-module.c (module_global_reference_p): New helper function. (value_to_lisp): Use it. (cherry picked from commit 6355a3ec62f43c9b99d483982ff851d32dd78891)
-rw-r--r--src/emacs-module.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 4269b0ba2ac..099a6a3cf25 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -78,6 +78,7 @@ To add a new module function, proceed as follows:
#include "emacs-module.h"
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
@@ -380,6 +381,28 @@ XMODULE_GLOBAL_REFERENCE (Lisp_Object o)
return XUNTAG (o, Lisp_Vectorlike, struct module_global_reference);
}
+/* Returns whether V is a global reference. Only used to check module
+ assertions. If V is not a global reference, increment *N by the
+ number of global references (for debugging output). */
+
+static bool
+module_global_reference_p (emacs_value v, ptrdiff_t *n)
+{
+ struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
+ /* Note that we can't use `hash_lookup' because V might be a local
+ reference that's identical to some global reference. */
+ for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
+ {
+ if (!EQ (HASH_KEY (h, i), Qunbound)
+ && &XMODULE_GLOBAL_REFERENCE (HASH_VALUE (h, i))->value == v)
+ return true;
+ }
+ /* Only used for debugging, so we don't care about overflow, just
+ make sure the operation is defined. */
+ INT_ADD_WRAPV (*n, h->count, n);
+ return false;
+}
+
static emacs_value
module_make_global_ref (emacs_env *env, emacs_value ref)
{
@@ -1217,10 +1240,8 @@ value_to_lisp (emacs_value v)
++num_environments;
}
/* Also check global values. */
- struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
- if (hash_lookup (h, v->v, NULL) != -1)
+ if (module_global_reference_p (v, &num_values))
goto ok;
- INT_ADD_WRAPV (num_values, h->count, &num_values);
module_abort (("Emacs value not found in %"pD"d values "
"of %"pD"d environments"),
num_values, num_environments);