Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(4517)

Issue 7241055: fix pdec() on INT_MIN

Can't Edit
Can't Publish+Mail
Start Review
Created:
11 years, 3 months ago by xi
Modified:
11 years, 1 month ago
Reviewers:
CC:
rsc, codebot
Visibility:
Public.

Description

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'); }

Patch Set 1 #

Unified diffs Side-by-side diffs Delta from patch set Stats (+4 lines, -4 lines) Patch
M src/cmd/rc/io.c View 2 chunks +4 lines, -4 lines 0 comments Download

Messages

Total messages: 5
xi
11 years, 3 months ago (2013-01-31 07:11:38 UTC) #1
rsc
I don't understand what's wrong with the existing code. Can you elaborate? Russ
11 years, 3 months ago (2013-01-31 15:48:27 UTC) #2
xi
On 2013/01/31 15:48:27, rsc wrote: > I don't understand what's wrong with the existing code. ...
11 years, 2 months ago (2013-03-05 08:10:18 UTC) #3
rsc
thanks
11 years, 1 month ago (2013-03-19 18:36:04 UTC) #4
rsc
11 years, 1 month ago (2013-03-19 18:36:53 UTC) #5
*** Submitted as
https://code.google.com/p/plan9port/source/detail?r=1bd8b25173d5 ***

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

Committer: Russ Cox <rsc@swtch.com>
Sign in to reply to this message.

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b