@@ -837,8 +837,8 @@ <h2 class="toc-title">Table of Contents</h2>
837837 <li><a href="#revision-history" id="toc-revision-history">Revision
838838 History</a>
839839 <ul>
840- <li><a href="#r0-february-2026-pre-tokyo -mailing" id="toc-r0-february-2026-pre-tokyo -mailing">R0: February 2026
841- (pre-Tokyo mailing)</a></li>
840+ <li><a href="#r0-february-2026-post-croydon -mailing" id="toc-r0-february-2026-post-croydon -mailing">R0: February 2026
841+ (post-Croydon mailing)</a></li>
842842 </ul></li>
843843 <li><a href="#the-need-for-escape-hatches" id="toc-the-need-for-escape-hatches">1. The Need for Escape
844844 Hatches</a></li>
@@ -859,17 +859,17 @@ <h2 id="abstract">Abstract</h2>
859859possible.”</p>
860860<hr />
861861<h2 id="revision-history">Revision History</h2>
862- <h3 id="r0-february-2026-pre-tokyo -mailing">R0: February 2026 (pre-Tokyo
863- mailing)</h3>
862+ <h3 id="r0-february-2026-post-croydon -mailing">R0: February 2026
863+ (post-Croydon mailing)</h3>
864864<ul>
865865<li>Initial version.</li>
866866</ul>
867867<hr />
868868<h2 id="the-need-for-escape-hatches">1. The Need for Escape Hatches</h2>
869869<p>Safe interfaces should be the default. They should validate input,
870870maintain invariants, and protect users from misuse. However, C++ also
871- needs an explicit path for trusted data - when the invariant is already
872- established at a boundary and re-validation is pure overhead.</p>
871+ needs an explicit path for trusted data - when the precondition is
872+ already satisfied at a boundary and re-validation is pure overhead.</p>
873873<p>This pattern appears in the standard library, in production Boost
874874libraries, and in the current <code>cstring_view</code> proposal. Three
875875independent examples follow.</p>
@@ -905,7 +905,7 @@ <h2 id="established-practice">3. Established Practice</h2>
905905encoding before extracting URL components. Repeating that validation
906906would be redundant. A separate function bypasses it at the trusted
907907boundary:</p>
908- <div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Escape hatch: invariant already established by the parser.</span></span>
908+ <div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Escape hatch: precondition already satisfied by the parser.</span></span>
909909<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>pct_string_view s <span class="op">=</span> make_pct_string_view_unsafe<span class="op">(</span>data<span class="op">,</span> size<span class="op">,</span> decoded_size<span class="op">);</span></span></code></pre></div>
910910<p>This pattern was adopted independently by three Boost libraries:
911911Boost.URL (<a href="https://github.com/boostorg/url/blob/develop/include/boost/url/pct_string_view.hpp"><code>make_pct_string_view_unsafe</code></a><sup>[4]</sup>),
@@ -918,9 +918,8 @@ <h2 id="application-level">4. Application Level</h2>
918918pointer and a filename length via <code>dirent</code>
919919(<code>d_name</code> and <code>d_namlen</code>) <a href="https://man.freebsd.org/cgi/man.cgi?query=readdir&sektion=3">FreeBSD
920920<code>readdir(3)</code></a><sup>[7]</sup> and <a href="https://cgit.freebsd.org/src/tree/sys/sys/dirent.h">FreeBSD
921- <code>dirent.h</code></a><sup>[8]</sup>. The common invariant for path
922- components is that names are null-terminated and do not contain embedded
923- null bytes <a href="https://pubs.opengroup.org/onlinepubs/9799919799/">POSIX Base
921+ <code>dirent.h</code></a><sup>[8]</sup>. POSIX requires that path
922+ components are null-terminated and contain no embedded null bytes <a href="https://pubs.opengroup.org/onlinepubs/9799919799/">POSIX Base
924923Definitions</a><sup>[9]</sup>. Rescanning each name in a validating
925924constructor repeats work the operating system already did.</p>
926925<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> visit_directory<span class="op">(</span>DIR<span class="op">*</span> dir<span class="op">)</span></span>
@@ -930,22 +929,23 @@ <h2 id="application-level">4. Application Level</h2>
930929<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a> <span class="at">const</span> <span class="dt">char</span><span class="op">*</span> p <span class="op">=</span> de<span class="op">-></span>d_name<span class="op">;</span></span>
931930<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a> <span class="bu">std::</span>size_t n <span class="op">=</span> de<span class="op">-></span>d_namlen<span class="op">;</span></span>
932931<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
933- <span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a> <span class="co">// Trusted boundary: OS already established the invariant .</span></span>
932+ <span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a> <span class="co">// Trusted boundary: OS already satisfied the precondition .</span></span>
934933<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a> cstring_view name <span class="op">=</span> cstring_view<span class="op">::</span>unsafe<span class="op">(</span>p<span class="op">,</span> n<span class="op">);</span></span>
935934<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a> consume<span class="op">(</span>name<span class="op">);</span></span>
936935<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
937936<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
938937<p>The safe path remains the default for untrusted input. The unsafe
939- path exists for proven invariants and zero additional runtime cost.</p>
938+ path exists for proven preconditions and zero additional runtime
939+ cost.</p>
940940<h2 id="conclusion">5. Conclusion</h2>
941941<p>The standard library already provides constrained defaults with
942942explicit broader counterparts. Production libraries independently
943943converge on the same pattern for trusted boundaries. This paper asks for
944944no wording and no poll. It asks the committee to recognize a design
945945value: safe by default, with explicit escape hatches where zero-cost
946946composition requires them.</p>
947- <p>The interaction between explicit escape hatches and hardened
948- precondition checking is a related question that deserves separate
947+ <p>How explicit escape hatches interact with Hardening, Contracts, and
948+ Erroneous Behavior is a related question that deserves separate
949949treatment.</p>
950950<hr />
951951<h1 id="acknowledgements">Acknowledgements</h1>
0 commit comments