[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2019-11-22 Thread pinskia at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

--- Comment #1 from Andrew Pinski  ---
No those are still officially considered a referencing. 

In fact all three cases:
&p->field does not dereference p, just as &*p and &p[i] do not.

Should be considered a deference even though the deference does not happen.

There are other similar bug reports that say similar things to the null pointer
case.

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2019-11-22 Thread amodra at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

--- Comment #2 from Alan Modra  ---
(In reply to Andrew Pinski from comment #1)
> No those are still officially considered a referencing. 
> 
> In fact all three cases:
> &p->field does not dereference p, just as &*p and &p[i] do not.
> 
> Should be considered a deference even though the deference does not happen.

The ISO C standard ISO/IEC 9899:1999 appears to disagree with you.

From 6.5.3.2
"3  The unary & operator returns the address of its operand. If the operand has
type ‘‘type’’, the result has type ‘‘pointer to type’’. If the operand is the
result of a unary * operator, neither that operator nor the & operator is
evaluated and the result is as if both were omitted, except that the
constraints on the operators still apply and the result is not an lvalue.
Similarly, if the operand is the result of a [] operator" [snip rest]

I do not see anything under "constraints on the operators" that precludes &*p
on a null p, in fact there is a note that says

"83) Thus, &*E is equivalent to E (even if E is a null pointer)" [snip rest]

So what is more official than the C standard that makes you say "those are
still officially considered a referencing"?

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2019-11-22 Thread pinskia at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

Andrew Pinski  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |DUPLICATE

--- Comment #3 from Andrew Pinski  ---
Dup of bug 80797.

*** This bug has been marked as a duplicate of bug 80797 ***

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2019-11-22 Thread pinskia at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

--- Comment #4 from Andrew Pinski  ---
(In reply to Andrew Pinski from comment #3)
> Dup of bug 80797.

What I mean by that is the regression is not a regression but rather a specific
change introduced in GCC 7 and that is the PR which was asking for this
specific change.

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2019-11-22 Thread amodra at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

Alan Modra  changed:

   What|Removed |Added

 Status|RESOLVED|REOPENED
   Last reconfirmed||2019-11-23
 Resolution|DUPLICATE   |---
 Ever confirmed|0   |1

--- Comment #5 from Alan Modra  ---
How is it that "clang does this" overrides the C standard?

And yes, I quite realise that the C standard does not explicitly say &p->field
does not dereference p, but the analogy with &p[i] is strong and the fact is
that &p->field does not cause a dereference.  So it ought to be good when p is
null.

I'll note that we are talking C here, not C++.

If you're going to close this bug again then do so with an explanation from a
language viewpoint as to why

void
lang_for_each_input_file (void (*func) (lang_input_statement_type *))
{
  lang_input_statement_type *f;

  for (f = &input_file_chain.head->input_statement;
   f != NULL;
   f = f->next_real_file)
if (f->flags.real)
  func (f);
}

is wrong.  I'm genuinely interested, not just pissed off that you've closed my
bug..

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2019-11-22 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

Jakub Jelinek  changed:

   What|Removed |Added

 CC||jsm28 at gcc dot gnu.org

--- Comment #6 from Jakub Jelinek  ---
CCing Joseph on the language lawyer part of the thing.

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2019-11-22 Thread amodra at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

--- Comment #7 from Alan Modra  ---
Here's another example, a typical offsetof.

#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2019-11-22 Thread pinskia at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

--- Comment #8 from Andrew Pinski  ---
(In reply to Alan Modra from comment #7)
> Here's another example, a typical offsetof.
> 
> #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)

That can never be a correct offsetof as that can never be a constant integer
expression in C or C++.  That is one of the reasons why GCC created
__builtin_offsetof (reading old history):
https://gcc.gnu.org/ml/gcc-bugs/2003-06/msg00482.html
:)

I Know there has been discussion about &a->f not being a NULL pointer even but
I cannot find it right now.

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2019-11-22 Thread pinskia at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

--- Comment #9 from Andrew Pinski  ---
https://gcc.gnu.org/ml/gcc-patches/2005-05/msg00076.html

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2019-11-22 Thread pinskia at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

--- Comment #10 from Andrew Pinski  ---
(In reply to Andrew Pinski from comment #8)
> I Know there has been discussion about &a->f not being a NULL pointer even
> but I cannot find it right now.

Finally found it: PR30368 comment #3:
The C standard still says that is undefined. 

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf :
6.5.3.2/3:
If the operand is the result of a unary * operator,
neither that operator nor the & operator is evaluated and the result is as if
both were
omitted, except that the constraints on the operators still apply and the
result is not an
lvalue. Similarly, if the operand is the result of a [] operator, neither the &
operator nor the unary * that is implied by the [] is evaluated and the result
is as if the & operator
were removed and the [] operator were changed to a + operator. Otherwise, the
result is
a pointer to the object or function designated by its operand.
 CUT 
In the case of &a->f, it is the same as &((*a).f).  There is no discussion in
the above about the . operator 

NOTE also the commentry comments in the margin:
Thus, &*E is equivalent to E (even if E is a null pointer), and &(E1[E2]) to
((E1)+(E2)). It is
always true that if E is a function designator or an lvalue that is a valid
operand of the unary &
operator, *&E is a function designator or an lvalue equal to E. If *P is an
lvalue and T is the name of
an object pointer type, *(T)P is an lvalue that has a type compatible with that
to which T points.
Among the invalid values for dereferencing a pointer by the unary * operator
are a null pointer, an
address inappropriately aligned for the type of object pointed to, and the
address of an object after the
end of its lifetime.
 CUT 
Again there is the no discussion about -> or . here.  So Again &a->f cannot be
null even if a is null.

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2019-11-23 Thread amodra at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

--- Comment #11 from Alan Modra  ---
Oh wow, so the line of reasoning relies on what the C standard *doesn't* say in
6.5.3.2.

I also think the deductions are somewhat suspect.  You say &p->f is the same as
&((*p).f), which is from p->f being the same as (*p).f.  While I agree that is
generally true, it's relying on note 79 in the spec isn't it?

79) If &E is a valid pointer expression (where & is the ‘‘address-of’’
operator, which generates a pointer to its operand), the expression (&E)->MOS
is the same as E.MOS.

But if we don't have &E, which we don't when p is the null pointer (by
6.3.2.3/3), then how can you use note 79 to say p->f is the same as (*p).f when
p is the null pointer?

Quite likely I'm missing something.  However, the fact that there is old C code
around from many years ago that uses the offsetof macro as I wrote it, and the
fact that no compiler on earth actually dereferences p in &p->f lends credence
to the idea that there is no dereference here.

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2019-11-25 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

Richard Biener  changed:

   What|Removed |Added

   Target Milestone|--- |8.4

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2020-01-31 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

Jakub Jelinek  changed:

   What|Removed |Added

 Status|REOPENED|RESOLVED
 Resolution|--- |INVALID

--- Comment #12 from Jakub Jelinek  ---
Joseph said on IRC:
I don't think that's valid (runtime undefined, the lvalue that is the operand
of & does not designate an object and neither of the other cases in the
constraints for & applies).
Thus closing as INVALID.

[Bug sanitizer/92634] [8/9/10 regression] -fsanitize=undefined erroneous null pointer check

2020-01-31 Thread amodra at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634

--- Comment #13 from Alan Modra  ---
Yes, I came to the conclusion myself that this is really nothing to do with
dereferencing.  So my original claim and Andrew's replies about dereferencing
are not relevant.  The standard says of unary &

"The operand of the unary & operator shall be either a function designator, the
result of a [] or unary * operator, or an lvalue that designates an object that
is not a bit-field and is not declared with the register storage-class
specifier."

We don't have a function designator, the result of a [] or unary *, so the &
operand must be an lvalue.  Of lvalues, the standard says (in part):

"if an lvalue does not designate an object when it is evaluated, the behavior
is undefined"

And that along with lack of a special case for &p->f is the language reason why
the binutils code was UB.