Re: enif_make_int64 => -0 for INT64_MIN with gcc 4.9.1
Anthony Ramine <[email protected]>
| Newsgroups | gmane.comp.lang.erlang.bugs |
|---|---|
| Message-ID | <[email protected]> |
There is also https://github.com/erlang/otp/pull/388 -- Anthony Ramine Le 4 août 2014 à 12:09, Lukas Larsson <[email protected]> a écrit : > Hello, > > I've added fixes for the two places that you have found bugs. I'll see if I can find some more errors from the sanitizers. > > Lukas > On 21/07/14 00:34, Tuncer Ayaz wrote: >> On Sun, Jul 20, 2014 at 11:56 PM, Tomas Abrahamsson wrote: >>> Hi, that sanitizer branch was most useful! I hope it will make it >>> into erlang. This is a run of the previous code with the sanitizers >>> merged into OTP-17.1.1: >> There are more sanitizers you can try out. Usan is comparatively >> low-impact, but the others cause considerable slowdowns, so don't be >> surprised about that. Asan and Tsan are not cheap, but easier to use >> than Valgrind. Also, you can try the same sanitizers with clang, but >> the names might differ. >> >>> Erlang/OTP 17 [erts-6.1.2] [source-cc894a7] [smp:4:4] >>> [async-threads:10] [kernel-poll:false] >>> >>> beam/utils.c:453:14: runtime error: negation of -9223372036854775808 >>> cannot be represented in type 'long long int'; cast to an unsigned >>> type to negate this value to itself >>> >>> beam/big.c:1548:4: runtime error: negation of -9223372036854775808 >>> cannot be represented in type 'long long int'; cast to an unsigned >>> type to negate this value to itself >> I just tried and found beam/big.c:1548:4, too. >> >>> The relevant files do indeed look like they are negating INT64_MIN. >>> (by the way, in utils.c, the erts_bld_sint64 takes else branch, >>> as expected, but advances szp by 0.) >>> >>> Cramming in an (unsigned long long int) cast in there >>> like the sanitizer error says, actually does make it >>> print -9223372036854775808 in the erlang code, >>> and no sanitizer error is printed anymore. >>> >>> utils.c >>> 443 Eterm >>> 444 erts_bld_sint64(Uint **hpp, Uint *szp, Sint64 si64) >>> 445 { >>> 446 Eterm res = THE_NON_VALUE; >>> 447 if (IS_SSMALL(si64)) { >>> 448 if (hpp) >>> 449 res = make_small((Sint) si64); >>> 450 } >>> 451 else { >>> 452 if (szp) >>> 453 *szp += ERTS_SINT64_HEAP_SIZE(si64); >>> 454 if (hpp) >>> 455 res = erts_sint64_to_big(si64, hpp); >>> 456 } >>> 457 return res; >>> 458 } >>> >>> big.h >>> 101 #define ERTS_SINT64_HEAP_SIZE(X) \ >>> 102 (IS_SSMALL((X)) \ >>> 103 ? 0 \ >>> 104 : ERTS_UINT64_BIG_HEAP_SIZE__((X) >= 0 ? (X) : -(X))) >>> >>> big.c >>> 1540 Eterm erts_sint64_to_big(Sint64 x, Eterm **hpp) >>> 1541 { >>> 1542 Eterm *hp = *hpp; >>> 1543 int neg; >>> 1544 if (x >= 0) >>> 1545 neg = 0; >>> 1546 else { >>> 1547 neg = 1; >>> 1548 x = -x; >>> 1549 } >>> ... >>> >>> I tried changing big.h:104 into: >>> : ERTS_UINT64_BIG_HEAP_SIZE__((X) >= 0 ? (X) : -((unsigned >>> long long int)X))) >>> and big.c:1548 into: >>> x = -(unsigned long long int)x; >>> >>> This could be an interesting quick check property, to verify no >>> undefined behaviours for various programs and values. >>> >>> BRs >>> Tomas >>> >>> On Sun, Jul 20, 2014 at 10:00 PM, Tuncer Ayaz wrote: >>>> On Sun, Jul 20, 2014 at 3:27 AM, Tomas Abrahamsson wrote: >>>>> Hi, >>>>> >>>>> I upgraded gcc from version 4.8.1 to 4.9.1, recompiled Erlang/OTP-17.1.1 >>>>> and my nif, and now enif_make_int64 creates -0 for INT64_MIN. >>>>> >>>>> % make test >>>>> erl -s int64nif go -s erlang halt >>>>> Erlang/OTP 17 [erts-6.1.1] [source] [smp:4:4] [async-threads:10] >>>>> [kernel-poll:false] >>>>> >>>>> -0 >>>>> >>>>> When Erlang was compiled with gcc-4.8.1, it printed -9223372036854775808, >>>>> I've attached the test programs, here are the important lines: >>>>> >>>>> go() -> >>>>> io:format("~p~n", [int64_from_nif()]). >>>>> >>>>> The NIF C-code contains: >>>>> >>>>> static ERL_NIF_TERM >>>>> int64_from_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) >>>>> { >>>>> return enif_make_int64(env, INT64_MIN); >>>>> } >>>>> >>>>> System information: >>>>> >>>>> OS: linux, 32-bit core i5, 3.14-1-686-pae (debian unstable) >>>>> Erlang/OTP: built from scratch (both times) from the OTP-17.1.1 git tag. >>>>> gcc: initially: gcc (Debian 4.8.1-10) 4.8.1 >>>>> with this one, it prints -9223372036854775808 >>>>> gcc: after upgrade: gcc (Debian 4.9.1-1) 4.9.1 >>>>> with this one, it prints -0 >>>>> >>>>> The only change I did was apt-get install gcc and then >>>>> rebuilding Erlang. >>>> I can confirm this on linux amd64. >>>> >>>> 17.1.2 gcc 4.8.2 -> -9223372036854775808 >>>> 17.1.2 gcc 4.9.0 -> -0 >>>> 17.1.2 gcc 4.9.1 -> -0 >>>> >>>> 16B03-1 gcc 4.8.2 -> -9223372036854775808 >>>> 16B03-1 gcc 4.9.0 -> 0 >>>> 16B03-1 gcc 4.9.1 -> 0 >>>> >>>> >>>> I suppose you're not able to distill this to stand-alone C code, right? >>>> >>>> I don't think it will reveal anything, but it's an easy way to >>>> find bugs, so maybe you can try building with >>>> -fsanitize=undefined. If you want to do that, I'd suggest to apply >>>> the patch available at https://github.com/erlang/otp/pull/429 and >>>> run "configure --enable-sanitizers=undefined". >> _______________________________________________ >> erlang-bugs mailing list >> [email protected] >> http://erlang.org/mailman/listinfo/erlang-bugs >> > > _______________________________________________ > erlang-bugs mailing list > [email protected] > http://erlang.org/mailman/listinfo/erlang-bugs _______________________________________________ erlang-bugs mailing list [email protected] http://erlang.org/mailman/listinfo/erlang-bugs