C++ Logo

sg12

Advanced search

Re: [ub] Draft 2 of Enhanced C/C++ memory and object model

From: Niall Douglas <s_sourceforge_at_[hidden]>
Date: Wed, 27 Mar 2019 10:45:11 +0000
CC to SG12 UB list, as I would doubt if Jens and Martin are on SG12.

On 26/03/2019 21:37, Uecker, Martin wrote:

> regarding 5.3 one should mention that P1434 defines a mechanism
> that make most unsafe pointer manipulations used in existing
> code well-defined via casts to uintptr_t and back. ("a fourth
> way out")

I'll freely admit that I don't understand the tainting model proposed by
P1434. It comes across to me as a compiler implementation detail, and
not something appropriate for a standardisation text.

I will try now to paraphrase my best understanding of the P1434 tainting
model.

If a pointer to a storage instance is cast to an integer (via memcpy,
passing through va_args, reinterpret casting), the storage instance
becomes tainted. An integer to pointer cast is only well defined if the
corresponding storage instance has been tainted.

A tainted storage instance is one where aliasing analysis is
jeopardized. Only untainted storage instances can be assumed by the
compiler to never alias.


I get the general thrust of this design, but I don't understand why
taint is important to mention. That seems to me a compiler
implementation detail, not for standardese.

I should also add that "storage instance" is defined differently between
my paper and P1434. In my paper, it is the storage backing the whole of
the originally allocated base object(s). So, for example, `new T[5]`
creates a *single* storage instance of an array of T.

In P1434, my current best understanding is that `new T[5]` would create
five separate storage instances, each of one T.

Due to this difference, provenance tracking is quite different. In my
paper, for a type:

struct A {
  int foo;
  struct B {
    int foo;
  } b;
};

... if one converts a pointer to A to a uintptr_t, adds the offset of B,
casts to a pointer to B, one gets a valid pointer to B with the same
storage instance as A. Pointer provenance is runtime checked on the
basis of the storage instance holding A. Thus so long as no pointers
derived from A* end up pointing outside A's storage instance, in my
implementation all is happy at the runtime checking level.

(Thus under my proposal, there are "gaps" in provenance checking
coverage, specifically if there were an array A[2], the pointers to
A[0].b and A[1].b would have the same provenance. In other words, under
my proposal I specifically don't do runtime provenance checking fidelity
*within* arrays, only *between* distinct arrays)


Under P1434, A's storage instance would become tainted, as would B's
storage instance, because under P1434 every object has its own storage
instance.

Myself, Martin and Jens have already discussed privately that the use of
the common phrase "storage instance" for different things is
undesirable. So I would suggest that during any further discussion we
instead say "DXXXX storage instance" and "P1434 storage instance" for
clarity.

Niall

Received on 2019-03-27 11:45:23