* 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