Strange bug found?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Strange bug found?

K K-2
Hi all,
am I wrong or is the following a bug in tinycc? 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))
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));
}

Sincerely,
Kernel

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Strange bug found?

Vincent Lefevre-10
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 6.5.3.2p4:

  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
satisfied.

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
  evaluated.

> 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

Regards,

--
Vincent Lefèvre <[hidden email]> - 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)

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
K K
Reply | Threaded
Open this post in threaded view
|

Re: Strange bug found?

K K

Thanks for the clarification, sounds plausible to me. The wish remains that a warning or an error message is displayed for undefined behaviour 😊

 

 

Von: [hidden email]
Gesendet: Donnerstag, 20. Februar 2020 13:06
An: [hidden email]
Betreff: Re: [Tinycc-devel] Strange bug found?

 

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 6.5.3.2p4:

  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
satisfied.

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
  evaluated.

> 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

Regards,

--
Vincent Lefèvre <[hidden email]> - 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)

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

 


_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel