[PATCH] D32199: [TBAASan] A TBAA Sanitizer (Clang)
Hal Finkel via cfe-commits
cfe-commits at lists.llvm.org
Mon May 1 16:17:55 PDT 2017
On 05/01/2017 02:35 PM, Krzysztof Parzyszek via cfe-commits wrote:
> On 5/1/2017 2:16 PM, Hal Finkel via cfe-commits wrote:
>>
>> On 05/01/2017 12:49 PM, Daniel Berlin wrote:
>>> On 04/21/2017 06:03 AM, Hal Finkel via Phabricator wrote:
>>>> ...
>>>>
>>>>
>>>> Our struct-path TBAA does the following:
>>>>
>>>> struct X { int a, b; };
>>>> X x { 50, 100 };
>>>> X *o = (X*) (((int*) &x) + 1);
>>>>
>>>> int a_is_b = o->a; // This is UB (or so we say)?
>>>>
>>>
>>> This is UB.
>>> A good resource for this stuff is
>>> http://www.cl.cam.ac.uk/~pes20/cerberus/
>>> <http://www.cl.cam.ac.uk/%7Epes20/cerberus/> which has a long
>>> document where they exlpore all of these and what various compilers
>>> do, along with what the standard seems to say.
>>
>> http://www.cl.cam.ac.uk/~pes20/cerberus/notes30-full.pdf is 172
>> pages, and so I may have missed it, but I don't see this case. Also,
>> I'd really like to see where the standard says this is UB. I don't
>> see it.
>>
>
> The last sentence of 8:
>
>
> 6.5.6 Additive operators
>
>
> 7 For the purposes of these operators, a pointer to an object that is
> not an element of an array behaves the same as a pointer to the first
> element of an array of length one with the type of the object as its
> element type.
>
> 8 When an expression that has integer type is added to or subtracted
> from a pointer, the result has the type of the pointer operand. If the
> pointer operand points to an element of an array object, and the array
> is large enough, the result points to an element offset from the
> original element such that the difference of the subscripts of the
> resulting and original array elements equals the integer expression.
> In other words, if the expression P points to the i-th element of an
> array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N
> (where N has the value n) point to, respectively, the i+n-th and
> i−n-th elements of the array object, provided they exist. Moreover, if
> the expression P points to the last element of an array object, the
> expression (P)+1 points one past the last element of the array object,
> and if the expression Q points one past the last element of an array
> object, the expression (Q)-1 points to the last element of the array
> object. If both the pointer operand and the result point to elements
> of the same array object, or one past the last element of the array
> object, the evaluation shall not produce an overflow; otherwise, the
> behavior is undefined. 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.
I certainly see your point, but I'm not sure it helps. It is true that
((int*) &x), not being a pointer to an array objected, when used as one,
is an array of length one. Thus, forming (((int*) &x) + 1) is valid,
being a one-past-the-end pointer, but cannot be used as the operand of a
unary * that is evaluated. That's not exactly what is going on here, but
I imagine one could argue some equivalence.
However, the example can also be written as:
struct X { int a, b; };
X x { 50, 100 };
X *o = (X*) &x.b;
int a_is_b = o->a; // This is UB (or so we say)?
and then the pointer arithmetic considerations don't seem to apply.
Thanks again,
Hal
>
> -Krzysztof
>
--
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory
More information about the cfe-commits
mailing list