On 6/12/21 10:08 AM, Giuseppe D'Angelo via Std-Proposals wrote:
Il 12/06/21 15:05, Ville Voutilainen via Std-Proposals ha scritto:
template <class T> remove_cvref_t<T> unsanitize(T&& t);

Returns: Either t or an unspecified value. If an unspecified value is
returned, the value and copies of the
value may be treated as indeterminate values until a subsequent
assignment or bitwise copy of a non-indeterminate
value is performed to the storage location where such a result or copy
of the result of unsanitize() is stored.

Basically the problem™ today would be that an implementation such as

#if defined(__has_feature) && __has_feature(memory_sanitizer)
  T x;
  return x;
#else
  return std::forward<T>(t);
#endif

would make MSAN trip on the return itself? (Didn't try on a complete testcase...)

Yeah, I haven't been able to think of a way to return a poisoned/tainted value that wouldn't already trip up an analyzer.

Perhaps this warrants a distinct class of values.  It doesn't fit in with the lvalue, xvalue, prvalue categories, but rather another kind of value property.  I think there is a distinction to be made between a poisoned value vs some other tainted or not-yet-sanitized value; any access of the former indicates a defect while for the latter, the value may be sanitized through validation (as is common when data is read from the network, a file, user input, etc...).

In either case, I think there is a need to be able to propagate poison/taint.  From the earlier example:

struct S {
  S() {}
  S(int v) : dm(v) {}

  // dm may only be used if a value was provided during construction.
  int dm = POISON(-1);
};

Copy construction of an S object (whether by a default copy constructor or user provided copy constructor, assuming the latter actually does a copy) should propagate poison/taint, not be itself indicative of a defect.  Drawing this line may be challenging or may require an opt-out mechanism like MemorySanitizer's no_sanitize attribute.

Tom.


Thanks,