* lib/obstack.in.h (_OBSTACK_CPTR): New macro.
(obstack_free): Use it instead of comparing pointers directly,
when the pointers might not point into the same object.
---
 ChangeLog        |  5 +++++
 lib/obstack.in.h | 17 ++++++++++++++---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index dc81c8c726..e63d92728a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2025-05-07  Paul Eggert  <egg...@cs.ucla.edu>
 
+       obstack: avoid undefined pointer comparison
+       * lib/obstack.in.h (_OBSTACK_CPTR): New macro.
+       (obstack_free): Use it instead of comparing pointers directly,
+       when the pointers might not point into the same object.
+
        obstack: check def before use in macros
        * lib/obstack.in.h (__attribute_noreturn__, __extension__):
        Be more careful about checking whether a macro is defined before
diff --git a/lib/obstack.in.h b/lib/obstack.in.h
index 7d2327977e..4b133c32cc 100644
--- a/lib/obstack.in.h
+++ b/lib/obstack.in.h
@@ -136,6 +136,16 @@
 # endif
 #endif
 
+/* A type suitable for comparing pointers regardless of whether they
+   point into the same object, e.g., (_OBSTACK_CPTR) p < (_OBSTACK_CPTR) q.
+   If possible, use uintptr_t to avoid undefined behavior and pacify
+   sanitizers.  Otherwise, use a pointer directly and hope for the best.  */
+#ifdef _OBSTACK_UINTPTR_TYPE
+typedef _OBSTACK_UINTPTR_TYPE _OBSTACK_CPTR;
+#else
+typedef char *_OBSTACK_CPTR;
+#endif
+
 /* These macros highlight the places where this implementation
    is different from the one in GNU libc.  */
 #if defined __GL_GNULIB_HEADER
@@ -478,7 +488,8 @@ extern int obstack_exit_failure;
   __extension__                                                                
      \
     ({ struct obstack *__o = (OBSTACK);                                        
      \
        void *__obj = (void *) (OBJ);                                         \
-       if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit)  \
+       if ((_OBSTACK_CPTR) __o->chunk < (_OBSTACK_CPTR) __obj                \
+           && (_OBSTACK_CPTR) __obj < (_OBSTACK_CPTR) __o->chunk_limit)        
      \
          __o->next_free = __o->object_base = (char *) __obj;                 \
        else                                                                  \
          __obstack_free (__o, __obj); })
@@ -579,8 +590,8 @@ extern int obstack_exit_failure;
 
 # define obstack_free(h, obj)                                                \
   ((h)->temp.tempptr = (void *) (obj),                                       \
-   (((h)->temp.tempptr > (void *) (h)->chunk                                 \
-     && (h)->temp.tempptr < (void *) (h)->chunk_limit)                       \
+   (((_OBSTACK_CPTR) (h)->chunk < (OBSTACK_CPTR) (h)->temp.tempptr           \
+     && (_OBSTACK_CPTR) (h)->temp.tempptr < (_OBSTACK_CPTR) (h)->chunk_limit) \
     ? (void) ((h)->next_free = (h)->object_base = (char *) (h)->temp.tempptr) \
     : __obstack_free ((h), (h)->temp.tempptr)))
 
-- 
2.49.0


Reply via email to