Subject: bug#49261: Segfault during loadup

From: Paul Eggert <[email-masked]>
Date: Wed, 14 Jul 2021 17:24:37 -0500

On 7/14/21 7:36 AM, Eli Zaretskii wrote:
> You are saying that there's some fundamental difference between
>
>    INT_MAX + 1
>
> and
>
>    (USE_LSB_TAG ? - (1 << GCTYPEBITS) : VAL_MAX)

Yes there's a fundamental difference. INT_MAX + 1 has a signed integer 
overflow that violates the C standard. Obviously GCC should diagnose it.

The other expression conforms to the C standard and there is no error or 
overflow there. There's no reason -Woverflow should provoke a diagnostic 
for it.

> Or between an expression 'x = FOO' and 'mask = BAR'?
I don't know what x, mask, FOO, and BAR refer to.

> the warning was valid, as the
> assignment loses significant bits.
I originally wrote it as "uintptr_t mask = VALMASK;" because I would 
rather avoid C casts when possible (they're too powerful and allow too 
many bugs to go undetected). I dislike the workaround that I installed 
because of (a) its unnecessary cast and (b) the lack of clarity that 
it's intended that we want to discard any bits outside UINTPTR_MAX ((b) 
was a problem with my original code too).

To try to fix both (a) and (b) I installed the attached further patch. 
It is a bit more verbose than what C requires, but the verbosity should 
help explain that masking with UINTPTR_MAX is intended, and the 
verbosity shouldn't hurt efficiency.

>From 0afbde4e68c1161a54f9593ecb5b66fe42aa0de4 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Wed, 14 Jul 2021 17:10:06 -0500
Subject: [PATCH] Pacify gcc -Woverflow more clearly

* src/alloc.c (mark_maybe_pointer): Make it clearer that ANDing
with UINTPTR_MAX is intended.  Omit a now-unnecessary cast.
---
 src/alloc.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/alloc.c b/src/alloc.c
index ee3fd64a00..8edcd06c84 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -4764,7 +4764,9 @@ mark_maybe_pointer (void *p, bool symbol_only)
 	 from Emacs source code, it can occur in some cases.  To fix
 	 this problem, the pdumper code should grok non-initial
 	 addresses, as the non-pdumper code does.  */
-      void *po = (void *) ((uintptr_t) p & (uintptr_t) VALMASK);
+      uintptr_t mask = VALMASK & UINTPTR_MAX;
+      uintptr_t masked_p = (uintptr_t) p & mask;
+      void *po = (void *) masked_p;
       char *cp = p;
       char *cpo = po;
       /* Don't use pdumper_object_p_precise here! It doesn't check the
-- 
2.25.1