DF-3589 / divzero_expr.c
/* * DF-3589 arithmetic proof (userland, same int32 semantics as the kernel). * * psmsmoother() sys/dev/misc/psm/psm.c:4337 does: * dxp = smoother->squelch_x / (div_x * multiplicator); * with div_x clamped to [div_min, div_max] and BOTH div_min, div_max and * multiplicator writable by ANY local user through the CTLFLAG_ANYBODY * sysctls hw.psm.synaptics.{div_min,div_max,multiplicator}, whose only * validation is `arg < 1` (psm.c:5767-5780). * * 65536 * 65536 wraps to 0 in signed 32-bit arithmetic => the divisor * becomes exactly 0 => idiv traps (#DE). In the kernel that is an * unrecoverable panic; in userland it is SIGFPE. This program proves the * wrap + trap on this exact toolchain. */ #include <stdio.h> #include <stdlib.h> int main(void) { volatile int div_min = 65536, div_max = 65536, multiplicator = 65536; volatile int squelch_x = 1234567; int div_x, dxp; div_x = div_max; /* imax(div_min, ...) == 65536 */ printf("div_x=%d multiplicator=%d\n", div_x, multiplicator); printf("int32 product div_x*multiplicator = %d (wrapped; 2^32 == 0)\n", div_x * multiplicator); fflush(stdout); dxp = squelch_x / (div_x * multiplicator); /* <-- traps here */ printf("no trap, dxp=%d (BUG NOT REPRODUCED)\n", dxp); return (0); } |