[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] Strange bug found?

From: Vincent Lefevre
Subject: Re: [Tinycc-devel] Strange bug found?
Date: Thu, 20 Feb 2020 13:05:45 +0100
User-agent: Mutt/1.12.1+33 (6a74e24e) vl-117499 (2019-06-23)

On 2020-02-20 07:08:48 +0000, K K wrote:
> am I wrong or is the following a bug in tinycc?

It may be a bug, but your example is based on undefined behavior
(see below), thus it is difficult to say (I mean that tcc does not
necessarily exploit the fact that this is undefined behavior, which
can explain why this works in general).

> I found this using the last git commit (btw. git repo is currently not 
> working again) and also in official 0.9.27, both on Windows.
> The output of the follwing short code is:
> 10 = 10 = 9, but of course should be 10 = 10 = 10
> The position of the marked line "double d = 0;" does not change the wrong 
> behaviour as long as it is before "double b[n];" Changing the line to "int i 
> = 0;" leads to correct behaviour.
> #include <stdio.h>
> #define ARRAYSIZE(a) (1[&(a)] - (a))

This is syntactically equivalent to

#define ARRAYSIZE(a) ( *(&(a) + 1) - (a) )

The ISO C standard says in

  The unary * operator denotes indirection. If the operand points to
  a function, the result is a function designator; if it points to
  an object, the result is an lvalue designating the object. If the
  operand has type “pointer to type”, the result has type “type”. If
  an invalid value has been assigned to the pointer, the behavior of
  the unary * operator is undefined.

The issue is that &(a) + 1 points to the end of the array, which is
neither a function, nor an object. Even though the * operator will
not read any value here, the conditions of the C standard are not

and this is confirmed by the end of 6.5.6p8 (about the + operator):

  If the result points one past the last element of the array object,
  it shall not be used as the operand of a unary * operator that is

> void main() {
>   double a[10];
>   size_t n = 10;
>   double d = 0; // <-- no failure if this is removed
>   double b[n];
>   printf("%u = %u = %u\n", ARRAYSIZE(a), n,   ARRAYSIZE(b));

Note that you should cast the 3 values to unsigned int.

> }
> Sincerely,
> Kernel


Vincent Lefèvre <address@hidden> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

reply via email to

[Prev in Thread] Current Thread [Next in Thread]