]> git.eshelyaron.com Git - emacs.git/commitdiff
Backport: Fix subtle bug when checking liveness of module values.
authorPhilipp Stephani <phst@google.com>
Sat, 25 Jul 2020 21:04:05 +0000 (23:04 +0200)
committerPhilipp Stephani <phst@google.com>
Fri, 31 Jul 2020 16:18:27 +0000 (18:18 +0200)
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)

src/emacs-module.c

index 4269b0ba2ac40f2d6bf8fa0211dcd60eabd19655..099a6a3cf25bbd6772866aa89ad576699e7d9260 100644 (file)
@@ -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);