Discussion:
Evaluated 'sizeof' arguments and null pointer dereference
(too old to reply)
Andrey Tarasevich
2015-06-11 05:07:31 UTC
Permalink
Raw Message
The language spec states that when argument of 'sizeof' has VLA type,
the argument is evaluated. Taking that into account, I wonder what
should happen in this situation

int n = 42;
int (*a)[n] = NULL;
sizeof a[0];

This is an example of a run-time evaluated 'sizeof'. However, formally
the argument contains a null-pointer dereference. Does this 'sizeof'
expression produce undefined behavior then? Or not?

Knowing the low-level idea behind VLA implementation, I understand that
run-time size of VLA is actually a piece of "sidecar" data that lives
besides the array, not embedded into the array itself. For this reason,
there are no material reason for the above expression to produce UB -
the 'sizeof' does not really need to access the array itself, it does
not really need to dereference the pointer.

However, the language spec says that the expression is evaluated, which
means that the potential for the UB is there. So, does it produce UB?
What was the intent?
--
Best regards,
Andrey Tarasevich
u***@berkeley.edu
2015-06-16 05:54:11 UTC
Permalink
Raw Message
Post by Andrey Tarasevich
The language spec states that when argument of 'sizeof' has VLA type,
the argument is evaluated. Taking that into account, I wonder what
should happen in this situation
int n = 42;
int (*a)[n] = NULL;
sizeof a[0];
This is an example of a run-time evaluated 'sizeof'. However, formally
the argument contains a null-pointer dereference. Does this 'sizeof'
expression produce undefined behavior then? Or not?
I would say so. It gets more interesting with side effects
which are also evaluated in that case.

...
Post by Andrey Tarasevich
However, the language spec says that the expression is evaluated, which
means that the potential for the UB is there. So, does it produce UB?
What was the intent?
Maybe they wanted to make evaluation of that expression be an all-or-nothing thing which may be less confusing than just evaluating the parts needed to determine the size (especially with side effects).
Post by Andrey Tarasevich
--
Best regards,
Andrey Tarasevich
Tim Rentsch
2015-07-10 19:12:49 UTC
Permalink
Raw Message
Post by Andrey Tarasevich
The language spec states that when argument of 'sizeof' has VLA type,
the argument is evaluated. Taking that into account, I wonder what
should happen in this situation
int n = 42;
int (*a)[n] = NULL;
sizeof a[0];
This is an example of a run-time evaluated 'sizeof'. However, formally
the argument contains a null-pointer dereference.
Technically that isn't quite right. There is undefined behavior
but that's because of the indexing operation, ie, the implied
underlying address arithmetic, not dereferencing (and in fact no
dereferencing occurs, because a[0] is of type array). If this
had been written 'sizeof *a' there would be no undefined
behavior; what causes undefined behavior when dereferencing a
null pointer is lvalue conversion, but here no lvalue conversion
occurs because what is referenced has an array type.
Post by Andrey Tarasevich
Does this 'sizeof'
expression produce undefined behavior then? Or not?
Yes, it does, because any address arithmetic (implied here by the
indexing operation) involving a null pointer is undefined
behavior.
Post by Andrey Tarasevich
Knowing the low-level idea behind VLA implementation, I understand
that run-time size of VLA is actually a piece of "sidecar" data that
lives besides the array, not embedded into the array itself. For this
reason, there are no material reason for the above expression to
produce UB -
the 'sizeof' does not really need to access the array itself, it does
not really need to dereference the pointer.
However, the language spec says that the expression is evaluated,
which means that the potential for the UB is there. So, does it
produce UB? What was the intent?
There is undefined behavior. IMO this result is what WG14
expected and intended, for much the same reasons given the other
responder - so that the rule for what happens is simple to state
and understand.
s***@casperkitty.com
2015-10-08 17:55:12 UTC
Permalink
Raw Message
Post by Tim Rentsch
There is undefined behavior. IMO this result is what WG14
expected and intended, for much the same reasons given the other
responder - so that the rule for what happens is simple to state
and understand.
What real advantage would that rule have over a rule which specified that
expressions that form part of an array dimension will be evaluated, but no
other expressions will? In all other scenarios where the size of a VLA
type isn't constant the compiler shouldn't have to do perform any action
with potentially-visible side-effects to ascertain the size.

Loading...