-
Notifications
You must be signed in to change notification settings - Fork 350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UB in ACPI_TO_INTEGER , ACPI_OFFSET #407
Comments
uintptr_t isn't portable (we support C90)... Do you have any other alternatives to uintptr_t? |
intptr is the portable definition. First choice would be losing the 30 year old C compiler support, or at least expecting anyone porting to such platforms to define the type. Second choice is some crappy compiler-dependent hack like:
(Per https://sourceforge.net/p/predef/wiki/DataModels/ and https://sourceforge.net/p/predef/wiki/Standards/ .) There is no guarantee that works everywhere, though. It works on most/all sane systems (but so does C99). I think invoking undefined behavior with modern compilers is probably a worse idea than dropping support for compilers that only support a dialect of C that has been obsolete for 19 years. (To be clear, even though I cited C11 in my initial comment, it was also undefined behavior in C99 and C89.) |
As it turns out, we already have the ACPI_UINTPTR_T macro that compiles to uintptr_t or void * depending on the compiler. Here's the change that we are thinking about. -#define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void, (void *) 0, (ACPI_SIZE) (i)) |
@cemeyer is this still needed? if so, please review the above comment and I'll make the changes. |
Yes, it's still relevant. I don't think the proposed change fixes the problem, though. The problematic part is the ACPI_ADD_PTR and ACPI_PTR_DIFF, not the type of the value passed as the second macro argument, which is immediately casted to |
We do in fact need to support old compilers, mostly for our commercial customers who do not like upgrading to new compilers. I don't know all of the users, so we don't really know how far back we must go. I don't see a problem with defining ACPI_OFFSET as: #define ACPI_OFFSET(d, f) (ACPI_SIZE) &(((d *) 0)->f) Which, BTW is the same implementation as visual studio: #define offsetof(s,m) (size_t)&(((s *)0)->m) |
@acpibob Hm, it's not clear to me whether that pointer construction is undefined behavior or not. You're generating a pointer to something which is outside the bounds of a valid object and also not a NULL pointer ( I think it may be valid to instead define an ephemeral object with automatic storage duration and perform much the same computation; an optimizing compiler could probably remove the storage for that object entirely. E.g.,
(This construction uses the GCC extension On the other hand, |
I ran into this issue again when building recent FreeBSD (which contains acpica) with clang 13.0.0:
This is indeed due to the line in
with
Looking through
This won't work for the |
Ok, in FreeBSD's own
which in acpica could be represented as:
|
Clang 13.0.0 produces a new -Werror warning about the ACPI_TO_INTEGER(p) and ACPI_OFFSET(d, f) macros in acpica's actypes.h: sys/contrib/dev/acpica/components/dispatcher/dsopcode.c:708:31: error: performing pointer subtraction with a null pointer has undefined behavior [-Werror,-Wnull-pointer-subtraction] ObjDesc->Region.Address = ACPI_PTR_TO_PHYSADDR (Table); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:664:41: note: expanded from macro 'ACPI_PTR_TO_PHYSADDR' #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) ^~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:661:41: note: expanded from macro 'ACPI_TO_INTEGER' #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:656:82: note: expanded from macro 'ACPI_PTR_DIFF' #define ACPI_PTR_DIFF(a, b) ((ACPI_SIZE) (ACPI_CAST_PTR (UINT8, (a)) - ACPI_CAST_PTR (UINT8, (b)))) ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. This problem of undefined behavior was also reported to acpica by @cem in 2018: acpica/acpica#407, but it seems there was never any fix committed for it upstream. Instead fix these locally, for ACPI_TO_INTEGER by simply casting the incoming pointer to ACPI_SIZE (which corresponds roughly to uintptr_t and size_t), and for ACPI_OFFSET by reusing our __offsetof definition from sys/cdefs.h. Reviewed by: emaste, kib, imp MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D31710
Clang 13.0.0 produces a new -Werror warning about the ACPI_TO_INTEGER(p) and ACPI_OFFSET(d, f) macros in acpica's actypes.h: sys/contrib/dev/acpica/components/dispatcher/dsopcode.c:708:31: error: performing pointer subtraction with a null pointer has undefined behavior [-Werror,-Wnull-pointer-subtraction] ObjDesc->Region.Address = ACPI_PTR_TO_PHYSADDR (Table); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:664:41: note: expanded from macro 'ACPI_PTR_TO_PHYSADDR' #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) ^~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:661:41: note: expanded from macro 'ACPI_TO_INTEGER' #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:656:82: note: expanded from macro 'ACPI_PTR_DIFF' #define ACPI_PTR_DIFF(a, b) ((ACPI_SIZE) (ACPI_CAST_PTR (UINT8, (a)) - ACPI_CAST_PTR (UINT8, (b)))) ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. This problem of undefined behavior was also reported to acpica by @cem in 2018: acpica/acpica#407, but it seems there was never any fix committed for it upstream. Instead fix these locally, for ACPI_TO_INTEGER by simply casting the incoming pointer to ACPI_SIZE (which corresponds roughly to uintptr_t and size_t), and for ACPI_OFFSET by reusing our __offsetof definition from sys/cdefs.h. Reviewed by: emaste, kib, imp Differential Revision: https://reviews.freebsd.org/D31710 (cherry picked from commit 130a690)
Clang 13.0.0 produces a new -Werror warning about the ACPI_TO_INTEGER(p) and ACPI_OFFSET(d, f) macros in acpica's actypes.h: sys/contrib/dev/acpica/components/dispatcher/dsopcode.c:708:31: error: performing pointer subtraction with a null pointer has undefined behavior [-Werror,-Wnull-pointer-subtraction] ObjDesc->Region.Address = ACPI_PTR_TO_PHYSADDR (Table); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:664:41: note: expanded from macro 'ACPI_PTR_TO_PHYSADDR' #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) ^~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:661:41: note: expanded from macro 'ACPI_TO_INTEGER' #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:656:82: note: expanded from macro 'ACPI_PTR_DIFF' #define ACPI_PTR_DIFF(a, b) ((ACPI_SIZE) (ACPI_CAST_PTR (UINT8, (a)) - ACPI_CAST_PTR (UINT8, (b)))) ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. This problem of undefined behavior was also reported to acpica by @cem in 2018: acpica/acpica#407, but it seems there was never any fix committed for it upstream. Instead fix these locally, for ACPI_TO_INTEGER by simply casting the incoming pointer to ACPI_SIZE (which corresponds roughly to uintptr_t and size_t), and for ACPI_OFFSET by reusing our __offsetof definition from sys/cdefs.h. Reviewed by: emaste, kib, imp Differential Revision: https://reviews.freebsd.org/D31710 (cherry picked from commit 130a690)
Clang 13.0.0 produces a new -Werror warning about the ACPI_TO_INTEGER(p) and ACPI_OFFSET(d, f) macros in acpica's actypes.h: sys/contrib/dev/acpica/components/dispatcher/dsopcode.c:708:31: error: performing pointer subtraction with a null pointer has undefined behavior [-Werror,-Wnull-pointer-subtraction] ObjDesc->Region.Address = ACPI_PTR_TO_PHYSADDR (Table); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:664:41: note: expanded from macro 'ACPI_PTR_TO_PHYSADDR' #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) ^~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:661:41: note: expanded from macro 'ACPI_TO_INTEGER' #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:656:82: note: expanded from macro 'ACPI_PTR_DIFF' #define ACPI_PTR_DIFF(a, b) ((ACPI_SIZE) (ACPI_CAST_PTR (UINT8, (a)) - ACPI_CAST_PTR (UINT8, (b)))) ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. This problem of undefined behavior was also reported to acpica by @cem in 2018: acpica/acpica#407, but it seems there was never any fix committed for it upstream. Instead fix these locally, for ACPI_TO_INTEGER by simply casting the incoming pointer to ACPI_SIZE (which corresponds roughly to uintptr_t and size_t), and for ACPI_OFFSET by reusing our __offsetof definition from sys/cdefs.h. Reviewed by: emaste, kib, imp MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D31710 (cherry picked from commit 130a690)
Clang 13.0.0 produces a new -Werror warning about the ACPI_TO_INTEGER(p) and ACPI_OFFSET(d, f) macros in acpica's actypes.h: sys/contrib/dev/acpica/components/dispatcher/dsopcode.c:708:31: error: performing pointer subtraction with a null pointer has undefined behavior [-Werror,-Wnull-pointer-subtraction] ObjDesc->Region.Address = ACPI_PTR_TO_PHYSADDR (Table); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:664:41: note: expanded from macro 'ACPI_PTR_TO_PHYSADDR' #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) ^~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:661:41: note: expanded from macro 'ACPI_TO_INTEGER' #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:656:82: note: expanded from macro 'ACPI_PTR_DIFF' #define ACPI_PTR_DIFF(a, b) ((ACPI_SIZE) (ACPI_CAST_PTR (UINT8, (a)) - ACPI_CAST_PTR (UINT8, (b)))) ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. This problem of undefined behavior was also reported to acpica by @cem in 2018: acpica/acpica#407, but it seems there was never any fix committed for it upstream. Instead fix these locally, for ACPI_TO_INTEGER by simply casting the incoming pointer to ACPI_SIZE (which corresponds roughly to uintptr_t and size_t), and for ACPI_OFFSET by reusing our __offsetof definition from sys/cdefs.h. Reviewed by: emaste, kib, imp MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D31710 (cherry picked from commit 130a690)
Clang 13.0.0 produces a new -Werror warning about the ACPI_TO_INTEGER(p) and ACPI_OFFSET(d, f) macros in acpica's actypes.h: sys/contrib/dev/acpica/components/dispatcher/dsopcode.c:708:31: error: performing pointer subtraction with a null pointer has undefined behavior [-Werror,-Wnull-pointer-subtraction] ObjDesc->Region.Address = ACPI_PTR_TO_PHYSADDR (Table); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:664:41: note: expanded from macro 'ACPI_PTR_TO_PHYSADDR' #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) ^~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:661:41: note: expanded from macro 'ACPI_TO_INTEGER' #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:656:82: note: expanded from macro 'ACPI_PTR_DIFF' #define ACPI_PTR_DIFF(a, b) ((ACPI_SIZE) (ACPI_CAST_PTR (UINT8, (a)) - ACPI_CAST_PTR (UINT8, (b)))) ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. This problem of undefined behavior was also reported to acpica by @cem in 2018: acpica/acpica#407, but it seems there was never any fix committed for it upstream. Instead fix these locally, for ACPI_TO_INTEGER by simply casting the incoming pointer to ACPI_SIZE (which corresponds roughly to uintptr_t and size_t), and for ACPI_OFFSET by reusing our __offsetof definition from sys/cdefs.h. Reviewed by: emaste, kib, imp MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D31710 (cherry picked from commit 130a690)
Clang 13.0.0 produces a new -Werror warning about the ACPI_TO_INTEGER(p) and ACPI_OFFSET(d, f) macros in acpica's actypes.h: sys/contrib/dev/acpica/components/dispatcher/dsopcode.c:708:31: error: performing pointer subtraction with a null pointer has undefined behavior [-Werror,-Wnull-pointer-subtraction] ObjDesc->Region.Address = ACPI_PTR_TO_PHYSADDR (Table); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:664:41: note: expanded from macro 'ACPI_PTR_TO_PHYSADDR' #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) ^~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:661:41: note: expanded from macro 'ACPI_TO_INTEGER' #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sys/contrib/dev/acpica/include/actypes.h:656:82: note: expanded from macro 'ACPI_PTR_DIFF' #define ACPI_PTR_DIFF(a, b) ((ACPI_SIZE) (ACPI_CAST_PTR (UINT8, (a)) - ACPI_CAST_PTR (UINT8, (b)))) ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. This problem of undefined behavior was also reported to acpica by @cem in 2018: acpica/acpica#407, but it seems there was never any fix committed for it upstream. Instead fix these locally, for ACPI_TO_INTEGER by simply casting the incoming pointer to ACPI_SIZE (which corresponds roughly to uintptr_t and size_t), and for ACPI_OFFSET by reusing our __offsetof definition from sys/cdefs.h. Reviewed by: emaste, kib, imp MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D31710
It is bogus in C to subtract arbitrary pointers that do not point to the same object (or one beyond the end of the object), and the use of difference for these is not needed. (C11 §6.5.6, constraint 9, p.93 of the last draft.)
C defines offsetof() in stddef.h since C89, but even if we are concerned about running on environments that do not support offsetof, it would be more correct to just cast the corresponding pointers to
uintptr_t
and skip the subtraction. NULL == 0, regardless of bit representation.I suggest (something along the lines of):
The text was updated successfully, but these errors were encountered: