URI: 
       trc: avoid undefined C - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 1bfec89b997c9544100128fec6e0b0c3757fdd11
   DIR parent 8a2a5b8f2568a665f00741994c1247f0f7d3dffe
  HTML Author: Xi Wang <xi.wang@gmail.com>
       Date:   Tue, 19 Mar 2013 14:36:50 -0400
       
       rc: avoid undefined C
       
       There are two bugs in pdec() on INT_MIN:
       
       * wrong output.
       
       `n = 1-n' should be `n = -1-n' when n is INT_MIN.
       
       * infinite loop.
       
       gcc optimizes `if(n>=0)' into `if(true)' because `-INT_MIN' (signed integer overflow) is undefined behavior in C, and gcc assumes the negation of a negative number must be positive.  The resulting binary keeps printing '-' forever given INT_MIN.
       
       Try the simplified pdec.c below.
       
       $ gcc pdec.c
       $ ./a.out -2147483648
       --214748364*
       
       $ gcc pdec.c -O2
       $ ./a.out -2147483648
       <infinite loop>
       
       $ gcc pdec.c -O2 -D__PATCH__
       $ ./a.out -2147483648
       -2147483648
       
       === pdec.c ===
       
       #include <stdio.h>
       #include <stdlib.h>
       #include <limits.h>
       
       #define io void
       
       void pchr(io *f, int c)
       {
               putchar(c);
       }
       
       void pdec(io *f, int n)
       {
               if(n<0){
       #ifndef __PATCH__
                       n=-n;
                       if(n>=0){
                               pchr(f, '-');
                               pdec(f, n);
                               return;
                       }
                       /* n is two's complement minimum integer */
                       n = 1-n;
       #else
                       if(n!=INT_MIN){
                               pchr(f, '-');
                               pdec(f, -n);
                               return;
                       }
                       /* n is two's complement minimum integer */
                       n = -(INT_MIN+1);
       #endif
                       pchr(f, '-');
                       pdec(f, n/10);
                       pchr(f, n%10+'1');
                       return;
               }
               if(n>9)
                       pdec(f, n/10);
               pchr(f, n%10+'0');
       }
       
       int main(int argc, char **argv)
       {
               int n = atoi(argv[1]);
               pdec(NULL, n);
               putchar('\n');
       }
       
       R=rsc
       CC=plan9port.codebot
       https://codereview.appspot.com/7241055
       
       Diffstat:
         M src/cmd/rc/io.c                     |       8 ++++----
       
       1 file changed, 4 insertions(+), 4 deletions(-)
       ---
   DIR diff --git a/src/cmd/rc/io.c b/src/cmd/rc/io.c
       t@@ -1,3 +1,4 @@
       +#include <limits.h>
        #include "rc.h"
        #include "exec.h"
        #include "io.h"
       t@@ -119,14 +120,13 @@ void
        pdec(io *f, int n)
        {
                if(n<0){
       -                n=-n;
       -                if(n>=0){
       +                if(n!=INT_MIN){
                                pchr(f, '-');
       -                        pdec(f, n);
       +                        pdec(f, -n);
                                return;
                        }
                        /* n is two's complement minimum integer */
       -                n = 1-n;
       +                n = -(INT_MIN+1);
                        pchr(f, '-');
                        pdec(f, n/10);
                        pchr(f, n%10+'1');