[Bug 287013] m4 code to display MIN_INT is unsafe

From: <bugzilla-noreply_at_freebsd.org>
Date: Fri, 23 May 2025 12:14:59 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=287013

            Bug ID: 287013
           Summary: m4 code to display MIN_INT is unsafe
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: bin
          Assignee: bugs@FreeBSD.org
          Reporter: eblake@redhat.com

The code for printing signed integers in m4 has a subtle bug when printing
MIN_INT: in twos-complement, -MIN_INT is still negative, so the code proceeds
to call pushback(digits[-8]) before short-circuiting any further iterations of
the digit loop.  Since digits[-8] is out-of-bounds, the compiler can perform
optimizations based on undefined C behavior.

https://cgit.freebsd.org/src/tree/usr.bin/m4/misc.c?id=878d53410f75dbd9401def736562c906f8fecc33#n124

For example, when I compiled the BSD sources for m4 on Linux with gcc, I see
the following behavior:

$ echo 'eval(-0x7fffffff-1)' | ~/m4bsd/m4
-

instead of the intended output of -2147483648.

The following patch ensures that this will not trigger an incorrect string or
other undefined behavior:

diff --git i/usr.bin/m4/misc.c w/usr.bin/m4/misc.c
index d641ec56afeb..afcf760de9bf 100644
--- i/usr.bin/m4/misc.c
+++ w/usr.bin/m4/misc.c
@@ -121,7 +121,7 @@ pbnum(int n)
 pbnumbase(int n, int base, int d)
 {
        static char digits[36] = "0123456789abcdefghijklmnopqrstuvwxyz";
-       int num;
+       unsigned int num;
        int printed = 0;

        if (base > 36)

-- 
You are receiving this mail because:
You are the assignee for the bug.