Skip to content

Commit f6ebbba

Browse files
committed
New issue from Jan Schultke: "std::start_lifetime_as inadvertently has undefined behavior due to use of std::bit_cast"
1 parent 58cb4a1 commit f6ebbba

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

xml/issue4168.xml

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4168" status="New">
5+
<title>`std::start_lifetime_as` inadvertently has undefined behavior due to use of `std::bit_cast`</title>
6+
<section><sref ref="[obj.lifetime]"/></section>
7+
<submitter>Jan Schultke</submitter>
8+
<date>23 Oct 2024</date>
9+
<priority>99</priority>
10+
11+
<discussion>
12+
<p>
13+
Consider the motivating example from
14+
<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2590r2.pdf">P2590R2: Explicit lifetime management</a>:
15+
</p>
16+
<blockquote style="border-left: 3px solid #ccc;padding-left: 15px;">
17+
<pre>
18+
struct X { int a, b; };
19+
20+
X* make_x() {
21+
X* p = std::start_lifetime_as&lt;X&gt;(myMalloc(sizeof(struct X));
22+
p-&gt;a = 1;
23+
p-&gt;b = 2;
24+
return p;
25+
}
26+
</pre>
27+
</blockquote>
28+
<p>
29+
Assuming that `myMalloc` does not initialize the bytes of storage, this example has undefined behavior because
30+
the value of the resulting object of trivially copyable type `X` is determined as if by calling
31+
<tt>std::bit_cast&lt;X&gt;(a)</tt> for the implicitly-created object `a` of type `X`
32+
(<sref ref="[obj.lifetime]"/> paragraph 3), whose object representation is filled with indeterminate bytes
33+
obtained from `myMalloc`. Such a call to `std::bit_cast` has undefined behavior because `std::bit_cast`
34+
does not tolerate the creation of an `int` where bits in the value representation are indeterminate
35+
(<sref ref="[bit.cast]"/> paragraph 2), and such an `int` is the smallest enclosing object of some of the
36+
indeterminate bits.
37+
</p>
38+
</discussion>
39+
40+
<resolution>
41+
<p>
42+
This wording is relative to <paper num="N4993"/>.
43+
</p>
44+
45+
<ol>
46+
<li><p>Modify <sref ref="[obj.lifetime]"/> as indicated:</p>
47+
48+
<blockquote class="note">
49+
<p>
50+
[<i>Editor's note</i>: The proposed resolution does not alter the behavior for erroneous bits. Therefore,
51+
a call to <tt>std::start_lifetime_as</tt> may have erroneous behavior when used on storage with indeterminate
52+
bits, despite not accessing that storage. An alternative resolution would be to produce objects whose value
53+
is erroneous.]
54+
</p>
55+
</blockquote>
56+
57+
<blockquote>
58+
<pre>
59+
template&lt;class T&gt;
60+
T* start_lifetime_as(void* p) noexcept;
61+
template&lt;class T&gt;
62+
const T* start_lifetime_as(const void* p) noexcept;
63+
template&lt;class T&gt;
64+
volatile T* start_lifetime_as(volatile void* p) noexcept;
65+
template&lt;class T&gt;
66+
const volatile T* start_lifetime_as(const volatile void* p) noexcept;
67+
</pre>
68+
<blockquote>
69+
<p>
70+
-1- <i>Mandates</i>: [&hellip;]
71+
<p/>
72+
-2- <i>Preconditions</i>: [&hellip;]
73+
<p/>
74+
-3- <i>Effects</i>: Implicitly creates objects (<sref ref="[intro.object]"/>) within the denoted region
75+
consisting of an object <tt><i>a</i></tt> of type `T` whose address is `p`, and objects nested within
76+
<tt><i>a</i></tt>, as follows: The object representation of <tt><i>a</i></tt> is the contents of the
77+
storage prior to the call to `start_lifetime_as`. The value of each created object <tt><i>o</i></tt>
78+
of trivially copyable type (<sref ref="[basic.types.general]"/>) `U` is determined in the same manner
79+
as for a call to <tt>bit_cast&lt;U&gt;(E)</tt> (<sref ref="[bit.cast]"/>), where `E` is an lvalue of
80+
type `U` denoting <tt><i>o</i></tt>, except that the storage is not accessed <ins>and that
81+
for each indeterminate bit <tt><i>b</i></tt> in the value representation of the result, the smallest
82+
object containing that bit <tt><i>b</i></tt> has indeterminate value where the behavior would otherwise
83+
be undefined</ins>. The value of any other created object is unspecified.
84+
</p>
85+
</blockquote>
86+
</blockquote>
87+
88+
</li>
89+
</ol>
90+
</resolution>
91+
</issue>

0 commit comments

Comments
 (0)