Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #148310

Re: sizeof object got by dereferencing uniniitalized pointer

From Ben Bacarisse <ben.usenet@bsb.me.uk>
Newsgroups comp.lang.c
Subject Re: sizeof object got by dereferencing uniniitalized pointer
Date 2019-11-30 11:19 +0000
Organization A noiseless patient Spider
Message-ID <875zj1393a.fsf@bsb.me.uk> (permalink)
References (8 earlier) <86eexr8qlh.fsf@linuxsc.com> <87v9r33211.fsf@bsb.me.uk> <86k17i7kuh.fsf@linuxsc.com> <87pnha2vhx.fsf@bsb.me.uk> <wwlEF.120234$P37.83682@fx33.iad>

Show all headers | View raw


Richard Damon <Richard@Damon-Family.org> writes:

> On 11/29/19 5:00 PM, Ben Bacarisse wrote:
>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>> 
>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>
>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>>
>>>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>>>
>>>>>> Thiago Adams <thiago.adams@gmail.com> writes:
>>>>>> <cut>
>>>>>>
>>>>>>> Only when applied to variably types, sizeof is in runtime.
>>>>>>>
>>>>>>>   int n = 10;
>>>>>>>
>>>>>>>   int(*buf)[n] = malloc(sizeof(int) * n);
>>>>>>
>>>>>> Why would you not write
>>>>>>
>>>>>>    int (*buf)[n] = malloc(sizof *buf);
>>>>>>
>>>>>> ?
>>>>>
>>>>> Perhaps because, technically speaking, the right-hand side here
>>>>> has undefined behavior?
>>>>
>>>> Yes, it has.  That has always puzzled me.  Do you think that this usage
>>>> was specifically being ruled out, or is it a casualty of having made an
>>>> overly simple decision[1]?
>>>
>>> I have now looked into this further and can offer a more informed
>>> answer.  More below.
>>>
>>>> This whole areas makes me uneasy.  I've never been able to find a
>>>> reasonable example where an expression operand of sizeof needs to be
>>>> evaluated[2] (as the standard mandates) but most compilers evaluate f in
>>>>
>>>>   sizeof (int[f()])
>>>>
>>>> despite the standard not explaining what it means to evaluate a type
>>>> (though its not hard to guess what is intended).  Do the rules make
>>>> sense to you?  [I note your comment about _Generic_ but taking
>>>> it out because it doesn't bear on what I have to say.]
>>>
>>> The rules now make sense to me.  The authors wanted to be sure (or
>>> so I believe, in case that needs saying) that they didn't miss any
>>> corner cases, and so used general wording.
>> 
>> I didn't say what I meant, sorry.  I wanted to ask if you think the
>> rules are the right ones.  I feel the sacrifice (to undefined behaviour)
>> of patterns like
>> 
>>   memset(ptr, 0, sizeof *ptr);
>> 
>> to be unfortunate.  Mind you, VLAs, and the even more useful variably
>> modified types, have been thrown under the bus anyway.
>> 
>
> That isn't a good example, as if ptr isn't valid the fact that sizeof
> might generate UB pales to the effect of doing a memset on what it
> points to will do.

Yes, thanks.  A chain of edits led to this silly example because I
wanted something other than

>   ptr = malloc(sizeof *ptr);

which had already come up.  I thought I'd used memcpy(d, s, sizeof *s)
but then edited it to something daft!

>
> on the other hand would be a reasonable example of what I think you are
> referring to. Making this technically Undefined behavior is regrettable,
> but if the choice is between making it UB, with the possibility that the
> implementation can define that it just works as expected, or having the
> standard make a promise that implementations can't meet, and thus be
> defective (or maybe they can do it but at great inefficiency) then it
> makes sense to err initially on the side of creating UB, and if desired,
> later the rules on the implementation can be tightened up, and things
> are backwards compatible, while adding restrictions on promises would be
> a breaking change.
>
>>> They did think about
>>> needless evaluation in 'sizeof' operands, and the Standard does
>>> have a provision which talks about that;  in fact that provision
>>> evolved while C99 was being written.
>> 
>> I would have argued for a limited form of evaluation -- evaluation
>> sufficient to determine the type.  I think the rules would not be too
>> complicated, and it would be the natural place to specify what
>> "evaluating" a type name means.
>> 
>>> (If anyone cares they might
>>> want to compare n869 to later versions of the C99 standard.)
>>>
>>> Now, I hear you ask, _what_ corner cases?  Here is one, taken from
>>> my recent reponse to Keith Thompson:
>>>
>>>     int foo = sizeof *(int (*)[ ident( 1 ) ]){ &something };
>>>
>>> This declaration is legal C99, provided of course there are
>>> suitable declarations for the identifiers 'something' and 'ident'
>>> in scope.  The operand is an expression, not a type name, although
>>> of course the expression does have a type name within it.  The
>>> operand expression needs to be evaluated, at least in part, in
>>> order to determine the result of the sizeof operator.
>> 
>> The same effect can be achieved without a compound literal by using a
>> cast.  Is there a subtle point I'm missing that relies on the CL?
>
> Yes, a cast can do the same too.
>> 
>>> Rather than
>>> concoct some carefully chosen language that does some sort of
>>> partial evalution for just those subexpressions that are needed
>>> to produce the result, the authors chose the simple rule that
>>> any VLA operand argument is evaluated.  That decision has some
>>> unfortunate consequences for undefined behavior, but in the 1990s
>>> there wasn't as much hysteria regarding undefined behavior as
>>> there is now.
>> 
>> Maybe " evaluation sufficient to determine the type" is more complicated
>> than I imagine.  I wonder if it was every considered.
>
> It may be that such wording seems imprecise. For instance, if the
> expression includes the comma operator, does the fact that the first
> value not effect the results mean it doesn't get evaluated? what if it
> includes a function call so there is a possibility of side effects? What
> if it somehow knows that it doesn't have side effects, but might
> invoke UB?

If the second operand is not a variable length array type, then the
first operand need not be evaluated.  But when there is a variably
modified type in the second, you raise an interesting point -- to what
extent should the standard specify when evaluation can be skipped?  For
example, in

  int n = 42, a[n];
  return sizeof (f(), a);

f() can't effect the type, not even if the call were sizeof (f(&n), a).
But in

  extern int n;
  n = 42;
  return sizeof *(f(), (int (*)[n])0);

it can.  I'd go for the simplest rule: evaluate if second operand is a
variably modified type.

As usual with simple rules, it's starting to get complicated!

-- 
Ben.

Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

sizeof object got by dereferencing uniniitalized pointer "V.Subramanian, India" <subramanian100in@yahoo.com> - 2019-11-28 05:20 -0800
  Re: sizeof object got by dereferencing uniniitalized pointer Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2019-11-28 05:37 -0800
    Re: sizeof object got by dereferencing uniniitalized pointer mark.bluemel@gmail.com - 2019-11-28 05:59 -0800
      Re: sizeof object got by dereferencing uniniitalized pointer David Brown <david.brown@hesbynett.no> - 2019-11-28 15:51 +0100
        Re: sizeof object got by dereferencing uniniitalized pointer Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2019-11-28 07:27 -0800
          Re: sizeof object got by dereferencing uniniitalized pointer Herbert Rosenau <nospam@hrosenau.de> - 2019-11-28 17:28 +0100
            Re: sizeof object got by dereferencing uniniitalized pointer Thiago Adams <thiago.adams@gmail.com> - 2019-11-28 08:51 -0800
              Re: sizeof object got by dereferencing uniniitalized pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-28 17:36 +0000
                Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-28 16:37 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-29 01:27 +0000
                Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-28 17:47 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-28 21:16 -0500
                Re: sizeof object got by dereferencing uniniitalized pointer Keith Thompson <kst-u@mib.org> - 2019-11-29 00:38 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-29 09:03 -0500
                Re: sizeof object got by dereferencing uniniitalized pointer Keith Thompson <kst-u@mib.org> - 2019-11-29 13:15 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Keith Thompson <kst-u@mib.org> - 2019-11-29 13:38 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-29 07:09 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-29 06:10 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-29 11:12 -0500
                Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-12-01 09:32 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-29 07:39 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-29 22:00 +0000
                Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-29 22:40 -0500
                Re: sizeof object got by dereferencing uniniitalized pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-30 11:19 +0000
                Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-30 09:01 -0500
                Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-12-01 10:28 -0800
              Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-28 12:49 -0500
                Re: sizeof object got by dereferencing uniniitalized pointer Thiago Adams <thiago.adams@gmail.com> - 2019-11-28 11:26 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Richard Damon <Richard@Damon-Family.org> - 2019-11-28 17:19 -0500
                Re: sizeof object got by dereferencing uniniitalized pointer Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-28 17:26 -0800
                Re: sizeof object got by dereferencing uniniitalized pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-28 22:34 +0000
          Re: sizeof object got by dereferencing uniniitalized pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-28 17:34 +0000
      You gotta wonder why people say things like this! (Was: sizeof object got by dereferencing uniniitalized pointer) gazelle@shell.xmission.com (Kenny McCormack) - 2019-11-28 17:19 +0000
    Re: sizeof object got by dereferencing uniniitalized pointer Keith Thompson <kst-u@mib.org> - 2019-11-28 14:55 -0800
      Re: sizeof object got by dereferencing uniniitalized pointer "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2019-11-30 15:28 -0800

csiph-web