Compiler optimisation bug
Nick Hibma
nick at van-laarhoven.org
Tue May 2 08:26:21 UTC 2017
There is a bug in sbin/dhclient.c for large expiry values on 32 bit platforms where time_t is a uint32_t (bug #218980, https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=218980). It is caused by a compiler optimisation that removes an if-statement. The code below shows the following output, clearly showing that the optimised case provides a different answer:
% cc -O2 main.c -o main.a && ./main.a
no opt: 0x7fffffff
with opt: 0xfffffffe
rephrased: 0x7fffffff
The code is as follows:
% cat main.c
#include <stdio.h>
#include <sys/time.h>
#define TIME_MAX 2147483647
time_t a = TIME_MAX;
time_t b = TIME_MAX;
time_t
add_noopt(time_t a, time_t b) __attribute__((optnone))
{
a += b;
if (a < b)
a = TIME_MAX;
return a;
}
time_t
add_withopt(time_t a, time_t b)
{
a += b;
if (a < b)
a = TIME_MAX;
return a;
}
time_t
add_rephrased(time_t a, time_t b)
{
if (a < 0 || a > TIME_MAX - b)
a = TIME_MAX;
else
a += b;
return a;
}
int
main(int argc, char **argv)
{
printf("no opt: 0x%08x\n", add_noopt(a, b));
printf("with opt: 0x%08x\n", add_withopt(a, b));
printf("rephrased: 0x%08x\n", add_rephrased(a, b));
}
Should this be reported to the clang folks? Or is this to be expected when abusing integer overflows this way?
Also: The underlying problem is the fact that time_t is a 32 bit signed int. Any pointers as to a general method of resolving these time_t issues?
Regards,
Nick Hibma
nick at van-laarhoven.org
-- Open Source: We stand on the shoulders of giants.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 873 bytes
Desc: Message signed with OpenPGP
URL: <http://lists.freebsd.org/pipermail/freebsd-current/attachments/20170502/f24c03af/attachment.sig>
More information about the freebsd-current
mailing list