This is an archive of the discontinued LLVM Phabricator instance.

[libcxx] Fix most undefined behavior in <list>
AbandonedPublic

Authored by EricWF on Aug 24 2015, 3:00 PM.

Details

Summary

This patch partially fixes the undefined behavior in <list>. The undefined behavior is caused by casting a pointer to __node_base __end_ to the derived type __node even though __end_ is not a sub-object of type __node.

See C++14 [expr.static.cast]p11

A prvalue of type “pointer to cv1 B,” where B is a class type, can be converted to a prvalue of type “pointer to cv2 D,” where D is a class derived (Clause 10) from B, if a valid standard conversion from “pointer to D” to “pointer to B” exists (4.10), cv2 is the same cv-qualification as, or greater cv-qualification than, cv1, and B is neither a virtual base class of D nor a base class of a virtual base class of D. The null pointer value (4.10) is converted to the null pointer value of the destination type. If the prvalue of type “pointer to cv1 B” points to a B that is actually a subobject of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the behavior is undefined.

This patch fixes the problem by adding an intermediary void cast so that the conversion acts as if it were a reinterpret_cast. A reinterpret cast between pointer types is not used because this will not work with fancy pointers. This depends on the wording in:

C++14 [expr.reinterpret.cast]p7

An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T”, the result is static_cast<cv T*>(static_cast<cv void*>(v)). Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value.

However, as @rsmith pointed out, this still has undefined behavior when the element_type stored in the list has a higher alignment requirement than that of a pointer.

I will post a patch that completely fixes this problem but that likely involves an ABI break.

Diff Detail

Event Timeline

EricWF updated this revision to Diff 33000.Aug 24 2015, 3:00 PM
EricWF retitled this revision from to [libcxx] Fix most undefined behavior in <list>.
EricWF updated this object.
EricWF added reviewers: mclow.lists, danalbert, rsmith.
EricWF added subscribers: cfe-commits, awi, rsmith.
mclow.lists edited edge metadata.Aug 26 2015, 1:10 PM

I like this because it localizes the weirdness into one routine self.
If we can't get D12999 applied due to ABI concerns, this will help a bunch.

EricWF abandoned this revision.Dec 16 2015, 4:11 PM

Abandoning for better solution in D12297.