Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20121216141203.GS23126@port70.net>
Date: Sun, 16 Dec 2012 15:12:03 +0100
From: Szabolcs Nagy <nsz@...t70.net>
To: musl@...ts.openwall.com
Subject: Re: spandsp build, lrint/sqrt/pow issue

* ojab <ojab@...b.ru> [2012-12-16 14:29:00 +0400]:
> Just FYI: I've bisected gcc, first bad commit is http://gcc.gnu.org/git/?p=gcc.git;a=commit;h=a75b1c712f1eaddc69919461ead67f4ac21663fe

thanks
i could not figure out what that commit did exactly

> Looks like a bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31871
> can be related.

this bug is different:
it is about that (void*)0 is not an integer constant expression
(which is sad: one cannot use pointer arithmetics in constant
expression context, so eg. offsetof cannot be implemented in c
eventhough the sizeof, alignment, padding information are all
available at compile-time)

> Please note that clang also fails the testcase and the
> errors/warnings are aligned with gcc's (in the attached files).
> 
> //wbr ojab

> /tmp/retcast.c:38:7: warning: cast to 'void *' from smaller integer type 'int' [-Wint-to-pointer-cast]
>   x = xpow(2,2);
>       ^
> /tmp/retcast.c:33:26: note: expanded from macro 'xpow'
> #define xpow(x,y)        __tg_real_complex_pow((x), (y))
>                          ^
> /tmp/retcast.c:24:38: note: expanded from macro '__tg_real_complex_pow'
> #define __tg_real_complex_pow(x, y) (__RETCAST_2(x, y)( \
>                                      ^
> /tmp/retcast.c:17:3: note: expanded from macro '__RETCAST_2'
>                 (void *)!((!__IS_FP(x) || !__IS_FP(y)) && __FLT((x)+(y)+1.0f))))0 : \
>                 ^

yes, it is exploited here that the type of a ?: expression
is different when one of the operands is (void*)0 vs (void*)1

(since we want the macro to expand to an expression with the
proper type, which is not possible in c99 without compiler help,
hence typeof hacks, this also shows why tgmath.h is a bad idea)

it seems (void*)1 is not allowed in newer gcc and clang
eventhough it's allowed by the standard:

http://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p5

note that the ?: expression is not evaluated, only its type is used

(if the expression was evaluated the warning might made sense:
(void*)1 could be a trap representation)

i think it's a gcc and clang bug if

 __typeof__(0 ? (int*)0 : (void*)1)

is not a valid type expression, it should work just like

 sizeof(0 ? (int*)0 : (void*)1)

which is a valid expression in iso c
(typeof is not defined by any standard but it should not
evaluate its argument like sizeof)

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.