Comparing pointer to a constant is strange
| Vulnerability potential | Low |
| DDoS potential | None |
Comparing pointer to a constant is strange as usually they are not constant
Impact
Comparing a pointer against a non-null integer constant — if (p == 0x1000),
if (p == 1), if (p == -1) — is suspicious because, outside of a few
documented sentinels, pointer values are decided at runtime by the allocator,
loader, and ASLR, so they are not portable constants. Such a comparison almost
never does what the author intended: it may be a hard-coded address that is only
valid on one platform or one build, a (void *)-1 sentinel that should have been
written symbolically (MAP_FAILED), or a typo where == was meant to compare
two pointers. The practical impact is a branch that is taken under the wrong
conditions, leading to logic errors that surface only on certain platforms or
builds.
Vulnerability potential
The security relevance is limited and indirect — this is mainly a portability and correctness smell.
- If a magic address is used as a sentinel for “invalid”/”sentinel” and a real allocation ever lands on that address (or the constant is wrong for the platform), the check passes or fails incorrectly, which can bypass a guard and allow a bad pointer to be used.
- Hard-coding an address can reflect an assumption that ASLR is disabled; baking such assumptions into code weakens defense-in-depth.
Beyond these edge cases there is no direct corruption or DoS path, so the severity is low.
Technical details
In C/C++ a pointer may be compared for equality against a null pointer constant
(0, NULL, nullptr); comparing against any other integer requires an
explicit cast and is only meaningful for known, ABI-defined addresses (e.g.
memory-mapped registers in embedded code, or sentinels like MAP_FAILED which
is (void *)-1).
Legitimate vs accidental uses
Legitimate: a comparison against (void *)-1 for mmap/sbrk failure, or
against a fixed hardware register address in a freestanding/embedded target.
These should be written through a named symbolic constant, not a bare literal.
Accidental: comparing a pointer to a small integer like 1 or 0x1000 usually
indicates confusion between a pointer and an index/flag, or a sentinel that
should be NULL.
Why runtime addresses are not constants
Heap addresses come from the allocator; stack addresses from the call chain; code/data addresses are relocated by the loader and randomized by ASLR. None are stable across runs, so equality against a literal is fragile by construction.
Catching the issue
Compiler
GCC/Clang warn on pointer/integer comparisons without a cast
(-Wint-conversion, and in C++ such a comparison is an error). Build with
-Wall -Wextra and do not silence these with casts unless the address is a
documented constant.
Static analysis
Clang-tidy, Cppcheck, Coverity, and PVS-Studio flag comparisons of pointers against magic numeric constants and suggest symbolic sentinels.
Review
Replace bare address literals with named constants (#define UART0_BASE
0x4000C000), use the platform-provided sentinel macros (MAP_FAILED,
INVALID_HANDLE_VALUE), and reserve pointer-to-null comparison for null checks.
How to reproduce
Compile with -Wall -Wextra; the compiler warns about comparison between
pointer and integer. The branch is effectively never taken as intended.
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int *p = malloc(sizeof *p);
/* Intends to detect a "special" pointer, but 0x1000 is an
arbitrary runtime-meaningless constant. */
if (p == (int *)0x1000) {
puts("special address");
} else {
puts("ordinary allocation"); /* essentially always taken */
}
free(p);
return 0;
}