[Bug sanitizer/81986] sanitizer detects negation of large number in string.c
kargl at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Sat Aug 26 16:36:00 GMT 2017
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81986
kargl at gcc dot gnu.org changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |dodji at gcc dot gnu.org,
| |dvyukov at gcc dot gnu.org,
| |jakub at gcc dot gnu.org,
| |kcc at gcc dot gnu.org,
| |marxin at gcc dot gnu.org
Component|libfortran |sanitizer
--- Comment #1 from kargl at gcc dot gnu.org ---
(In reply to Vittorio Zecca from comment #0)
> ! from test case pr66311.f90
> ! must be compiled and run
> ! libgfortran/runtime/string.c:199:11: runtime error: negation of
> 0x80000000000000000000000000000000 cannot be represented in type '__int128';
> cast to an unsigned type to negate this value to itself
> character(len=100) :: buffer
> write(buffer,*) -huge(0_16)-1
> end
Doesn't look like a gfortran problem other than gfortran uses GCC's
__int128 type and its middle/backend machinery. If you compile
your code with -fdump-tree-original, you get in a.f90.003t.original
{
static integer(kind=16) C.3427 = -0x80000000000000000000000000000000;
_gfortran_transfer_integer_write (&dt_parm.0, &C.3427, 16);
}
Changing your code to
character(len=100) :: buffer
write(buffer,*) -huge(0_4)-1
print '(A,Z8)', trim(buffer)// ' 0x', -huge(0_4)-1
end
where I added the print statement gives
troutmask:sgk[264] gfortran6 -static -o z -fdump-tree-original a.f90 && ./z
-2147483648 0x80000000
and a.f90.003t.original contains
{
static integer(kind=4) C.3427 = -2147483648;
_gfortran_transfer_integer_write (&dt_parm.0, &C.3427, 4);
}
Note the difference between using a decimal representation for the
constant and the hexidecimal representation in the *.original file.
But, a more interesting result occurs for
int
main(void)
{
__int128 i,j;
i = ((__int128)1) << 127;
j = (-((__int128)1)) << 127;
return 0;
}
% /usr/local/bin/gcc6 -fdump-tree-original -c a.c
%/ cat a.c.003t.original
;; Function main (null)
;; enabled by -tree-original
{
__int128 i;
__int128 j;
__int128 i;
__int128 j;
i = -0x80000000000000000000000000000000;
j = -0x80000000000000000000000000000000;
}
return 0;
Why is this interesting? Well, consider the simpler case
int
main(void)
{
int i,j;
i = ((int)1) << 31;
j = -(((int)1) << 31);
return 0;
}
/usr/local/bin/gcc6 -fdump-tree-original -c a.c
a.c: In function 'main':
a.c:9:8: warning: integer overflow in expression [-Woverflow]
j = -(((int)1)<<31);
^
%cat a.c.003t.original
;; Function main (null)
;; enabled by -tree-original
{
int i;
int j;
int i;
int j;
i = -2147483648;
j = -2147483648(OVF);
return 0;
}
Note, both the warning that GCC issues and the (OVF) annotation.
So, in summary, not a gfortran. Someone needs to teach the sanitizers
about GCC's __int128 or someone needs to fix the handling of __int128
to mirror the behavior observed for a plain old int.
More information about the Gcc-bugs
mailing list