<!doctype html><html lang="en">
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
  <title>P2723R1: Zero-initialize objects of automatic storage duration</title>
<style data-fill-with="stylesheet">/******************************************************************************
 *                   Style sheet for the W3C specifications                   *
 *
 * Special classes handled by this style sheet include:
 *
 * Indices
 *   - .toc for the Table of Contents (<ol class="toc">)
 *     + <span class="secno"> for the section numbers
 *   - #toc for the Table of Contents (<nav id="toc">)
 *   - ul.index for Indices (<a href="#ref">term</a><span>, in §N.M</span>)
 *   - table.index for Index Tables (e.g. for properties or elements)
 *
 * Structural Markup
 *   - table.data for general data tables
 *     -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
 *     -> use <table class='complex data'> for extra-complex tables
 *     -> use <td class='long'> for paragraph-length cell content
 *     -> use <td class='pre'> when manual line breaks/indentation would help readability
 *   - dl.switch for switch statements
 *   - ol.algorithm for algorithms (helps to visualize nesting)
 *   - .figure and .caption (HTML4) and figure and figcaption (HTML5)
 *     -> .sidefigure for right-floated figures
 *   - ins/del
 *
 * Code
 *   - pre and code
 *
 * Special Sections
 *   - .note       for informative notes             (div, p, span, aside, details)
 *   - .example    for informative examples          (div, p, pre, span)
 *   - .issue      for issues                        (div, p, span)
 *   - .assertion  for assertions                    (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *
 * Definition Boxes
 *   - pre.def   for WebIDL definitions
 *   - table.def for tables that define other entities (e.g. CSS properties)
 *   - dl.def    for definition lists that define other entitles (e.g. HTML elements)
 *
 * Numbering
 *   - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
 *   - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
 *   - ::before styled for CSS-generated issue/example/figure numbers:
 *     -> Documents wishing to use this only need to add
 *        figcaption::before,
 *        .caption::before { content: "Figure "  counter(figure) " ";  }
 *        .example::before { content: "Example " counter(example) " "; }
 *        .issue::before   { content: "Issue "   counter(issue) " ";   }
 *
 * Header Stuff (ignore, just don't conflict with these classes)
 *   - .head for the header
 *   - .copyright for the copyright
 *
 * Miscellaneous
 *   - .overlarge for things that should be as wide as possible, even if
 *     that overflows the body text area. This can be used on an item or
 *     on its container, depending on the effect desired.
 *     Note that this styling basically doesn't help at all when printing,
 *     since A4 paper isn't much wider than the max-width here.
 *     It's better to design things to fit into a narrower measure if possible.
 *   - js-added ToC jump links (see fixup.js)
 *
 ******************************************************************************/

/* color variables included separately for reliability */

/******************************************************************************/
/*                                   Body                                     */
/******************************************************************************/

	html {
		color: black;
		color: var(--text);
		background-color: white;
		background-color: var(--bg);
	}

	body {
		counter-reset: example figure issue;

		/* Layout */
		max-width: 50em;               /* limit line length to 50em for readability   */
		margin: 0 auto;                /* center text within page                     */
		padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
		padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag     */

		/* Typography */
		line-height: 1.5;
		font-family: sans-serif;
		widows: 2;
		orphans: 2;
		word-wrap: break-word;
		overflow-wrap: break-word;
		hyphens: auto;

		background: transparent top left fixed no-repeat;
		background-size: 25px auto;
	}


/******************************************************************************/
/*                         Front Matter & Navigation                          */
/******************************************************************************/

/** Header ********************************************************************/

	div.head { margin-bottom: 1em }
	div.head hr { border-style: solid; }

	div.head h1 {
		font-weight: bold;
		margin: 0 0 .1em;
		font-size: 220%;
	}

	div.head h2 { margin-bottom: 1.5em;}

/** W3C Logo ******************************************************************/

	.head .logo {
		float: right;
		margin: 0.4rem 0 0.2rem .4rem;
	}

	.head img[src*="logos/W3C"] {
		display: block;
		border: solid #1a5e9a;
		border: solid var(--logo-bg);
		border-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		background: var(--logo-bg);
		color: white;
		color: var(--logo-text);
		font-weight: bold;
	}

	.head a:hover > img[src*="logos/W3C"],
	.head a:focus > img[src*="logos/W3C"] {
		opacity: .8;
	}

	.head a:active > img[src*="logos/W3C"] {
		background: #c00;
		background: var(--logo-active-bg);
		border-color: #c00;
		border-color: var(--logo-active-bg);
	}

	/* see also additional rules in Link Styling section */

/** Copyright *****************************************************************/

	p.copyright,
	p.copyright small { font-size: small }

/** Back to Top / ToC Toggle **************************************************/

	@media print {
		#toc-nav {
			display: none;
		}
	}
	@media not print {
		#toc-nav {
			position: fixed;
			z-index: 2;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

			height: 1.33em;
			padding: .1em 0.3em;
			margin: 0;

			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;

			color: #707070;
			color: var(--tocnav-normal-text);
			background: white;
			background: var(--tocnav-normal-bg);
		}
		#toc-nav > a:hover,
		#toc-nav > a:focus {
			color: black;
			color: var(--tocnav-hover-text);
			background: #f8f8f8;
			background: var(--tocnav-hover-bg);
		}
		#toc-nav > a:active {
			color: #c00;
			color: var(--tocnav-active-text);
			background: white;
			background: var(--tocnav-active-bg);
		}

		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		/* statusbar gets in the way on keyboard focus; remove once browsers fix */
		#toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
			padding-bottom: 1.5rem;
		}

		#toc-nav:not(:hover) > a:not(:focus) > span + span {
			/* Ideally this uses :focus-within on #toc-nav */
			display: none;
		}
		#toc-nav > a > span + span {
			padding-right: 0.2em;
		}
	}

/** ToC Sidebar ***************************************************************/

	/* Floating sidebar */
	@media screen {
		body.toc-sidebar #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			max-width: 80%;
			max-width: calc(100% - 2em - 26px);
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			color: black;
			color: var(--tocsidebar-text);
			background: inherit;
			background-color: #f7f8f9;
			background-color: var(--tocsidebar-bg);
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
			box-shadow: -.1em 0 .25em var(--tocsidebar-shadow) inset;
		}
		body.toc-sidebar #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
			color: var(--tocsidebar-heading-text);
		}
		body.toc-sidebar #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	/* Hide main scroller when only the ToC is visible anyway */
	@media screen and (max-width: 28em) {
		body.toc-sidebar {
			overflow: hidden;
		}
	}

	/* Sidebar with its own space */
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			color: black;
			color: var(--tocsidebar-text);
			background: inherit;
			background-color: #f7f8f9;
			background-color: var(--tocsidebar-bg);
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
			box-shadow: -.1em 0 .25em var(--tocsidebar-shadow) inset;
		}
		body:not(.toc-inline) #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
			color: var(--tocsidebar-heading-text);
		}

		body:not(.toc-inline) {
			padding-left: 29em;
		}
		/* See also Overflow section at the bottom */

		body:not(.toc-inline) #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) {
			margin: 0 4em;
		}
	}

/******************************************************************************/
/*                                Sectioning                                  */
/******************************************************************************/

/** Headings ******************************************************************/

	h1, h2, h3, h4, h5, h6, dt {
		page-break-after: avoid;
		page-break-inside: avoid;
		font: 100% sans-serif;   /* Reset all font styling to clear out UA styles */
		font-family: inherit;    /* Inherit the font family. */
		line-height: 1.2;        /* Keep wrapped headings compact */
		hyphens: manual;         /* Hyphenated headings look weird */
	}

	h2, h3, h4, h5, h6 {
		margin-top: 3rem;
	}

	h1, h2, h3 {
		color: #005A9C;
		color: var(--heading-text);
	}

	h1 { font-size: 170%; }
	h2 { font-size: 140%; }
	h3 { font-size: 120%; }
	h4 { font-weight: bold; }
	h5 { font-style: italic; }
	h6 { font-variant: small-caps; }
	dt { font-weight: bold; }

/** Subheadings ***************************************************************/

	h1 + h2,
	#subtitle {
		/* #subtitle is a subtitle in an H2 under the H1 */
		margin-top: 0;
	}
	h2 + h3,
	h3 + h4,
	h4 + h5,
	h5 + h6 {
		margin-top: 1.2em; /* = 1 x line-height */
	}

/** Section divider ***********************************************************/

	:not(.head) > :not(.head) + hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		color: black;
		color: var(--hr-text);
		border: transparent solid 0;
		background: transparent;
	}
	:not(.head) > hr::before {
		content: "\2727\2003\2003\2727\2003\2003\2727";
	}

/******************************************************************************/
/*                            Paragraphs and Lists                            */
/******************************************************************************/

	p {
		margin: 1em 0;
	}

	dd > p:first-child,
	li > p:first-child {
		margin-top: 0;
	}

	ul, ol {
		margin-left: 0;
		padding-left: 2em;
	}

	li {
		margin: 0.25em 0 0.5em;
		padding: 0;
	}

	dl dd {
		margin: 0 0 .5em 2em;
	}

	.head dd + dd { /* compact for header */
		margin-top: -.5em;
	}

	/* Style for algorithms */
	ol.algorithm ol:not(.algorithm),
	.algorithm > ol ol:not(.algorithm) {
	 border-left: 0.5em solid #DEF;
	 border-left: 0.5em solid var(--algo-border);
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	  padding: .5em;
	  border: thin solid #ddd;
	  border: thin solid var(--algo-border);
	  border-radius: .5em;
	  margin: .5em calc(-0.5em - 1px);
	}
	[data-algorithm]:not(.heading) > :first-child {
	  margin-top: 0;
	}
	[data-algorithm]:not(.heading) > :last-child {
	  margin-bottom: 0;
	}

	/* Style for switch/case <dl>s */
	dl.switch > dd > ol.only,
	dl.switch > dd > .only > ol {
	 margin-left: 0;
	}
	dl.switch > dd > ol.algorithm,
	dl.switch > dd > .algorithm > ol {
	 margin-left: -2em;
	}
	dl.switch {
	 padding-left: 2em;
	}
	dl.switch > dt {
	 text-indent: -1.5em;
	 margin-top: 1em;
	}
	dl.switch > dt + dt {
	 margin-top: 0;
	}
	dl.switch > dt::before {
	 content: '\21AA';
	 padding: 0 0.5em 0 0;
	 display: inline-block;
	 width: 1em;
	 text-align: right;
	 line-height: 0.5em;
	}

/** Terminology Markup ********************************************************/


/******************************************************************************/
/*                                 Inline Markup                              */
/******************************************************************************/

/** Terminology Markup ********************************************************/
	dfn   { /* Defining instance */
		font-weight: bolder;
	}
	a > i { /* Instance of term */
		font-style: normal;
	}
	dt dfn code, code.idl {
		font-size: medium;
	}
	dfn var {
		font-style: normal;
	}

/** Change Marking ************************************************************/

	del {
		color: red;
		color: var(--del-text);
		background: transparent;
		background: var(--del-bg);
		text-decoration: line-through;
	}
	ins {
		color: #080;
		color: var(--ins-text);
		background: transparent;
		background: var(--ins-bg);
		text-decoration: underline;
	}

/** Miscellaneous improvements to inline formatting ***************************/

	sup {
		vertical-align: super;
		font-size: 80%
	}

/******************************************************************************/
/*                                    Code                                    */
/******************************************************************************/

/** General monospace/pre rules ***********************************************/

	pre, code, samp {
		font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
		font-size: .9em;
		hyphens: none;
		text-transform: none;
		text-align: left;
		text-align: start;
		font-variant: normal;
		orphans: 3;
		widows: 3;
		page-break-before: avoid;
	}
	pre code,
	code code {
		font-size: 100%;
	}

	pre {
		margin-top: 1em;
		margin-bottom: 1em;
		overflow: auto;
	}

/** Inline Code fragments *****************************************************/

  /* Do something nice. */

/******************************************************************************/
/*                                    Links                                   */
/******************************************************************************/

/** General Hyperlinks ********************************************************/

	/* We hyperlink a lot, so make it less intrusive */
	a[href] {
		color: #034575;
		color: var(--a-normal-text);
		text-decoration: none;
		border-bottom: 1px solid #707070;
		border-bottom: 1px solid var(--a-normal-underline);
		/* Need a bit of extending for it to look okay */
		padding: 0 1px 0;
		margin: 0 -1px 0;
	}
	a:visited {
		color: #034575;
		color: var(--a-visited-text);
		border-bottom-color: #bbb;
		border-bottom-color: var(--a-visited-underline);
	}

	/* Use distinguishing colors when user is interacting with the link */
	a[href]:focus,
	a[href]:hover {
		background: #f8f8f8;
		background: rgba(75%, 75%, 75%, .25);
		background: var(--a-hover-bg);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	a[href]:active {
		color: #c00;
		color: var(--a-active-text);
		border-color: #c00;
		border-color: var(--a-active-underline);
	}

	/* Backout above styling for W3C logo */
	.head .logo,
	.head .logo a {
		border: none;
		text-decoration: none;
		background: transparent;
	}

/******************************************************************************/
/*                                    Images                                  */
/******************************************************************************/

	img {
		border-style: none;
	}

	img, svg {
		/* Intentionally not color-scheme aware. */
		background: white;
	}

	/* For autogen numbers, add
	   .caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
	*/

	figure, .figure, .sidefigure {
		page-break-inside: avoid;
		text-align: center;
		margin: 2.5em 0;
	}
	.figure img,    .sidefigure img,    figure img,
	.figure object, .sidefigure object, figure object {
		max-width: 100%;
		margin: auto;
		height: auto;
	}
	.figure pre, .sidefigure pre, figure pre {
		text-align: left;
		display: table;
		margin: 1em auto;
	}
	.figure table, figure table {
		margin: auto;
	}
	@media screen and (min-width: 20em) {
		.sidefigure {
			float: right;
			width: 50%;
			margin: 0 0 0.5em 0.5em
		}
	}
	.caption, figcaption, caption {
		font-style: italic;
		font-size: 90%;
	}
	.caption::before, figcaption::before, figcaption > .marker {
		font-weight: bold;
	}
	.caption, figcaption {
		counter-increment: figure;
	}

	/* DL list is indented 2em, but figure inside it is not */
	dd > .figure, dd > figure { margin-left: -2em }

/******************************************************************************/
/*                             Colored Boxes                                  */
/******************************************************************************/

	.issue, .note, .example, .assertion, .advisement, blockquote {
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	.issue,
	.note,
	.example,
	.advisement,
	.assertion,
	blockquote {
		margin: 1em auto;
	}
	.note  > p:first-child,
	.issue > p:first-child,
	blockquote > :first-child {
		margin-top: 0;
	}
	blockquote > :last-child {
		margin-bottom: 0;
	}


	.issue::before, .issue > .marker,
	.example::before, .example > .marker,
	.note::before, .note > .marker,
	details.note > summary > .marker {
		text-transform: uppercase;
		padding-right: 1em;
	}

	.example::before, .example > .marker {
		display: block;
		padding-right: 0em;
	}

/** Blockquotes ***************************************************************/

	blockquote {
		border-color: silver;
		border-color: var(--blockquote-border);
		background: transparent;
		background: var(--blockquote-bg);
		color: currentcolor;
		color: var(--blockquote-text);
	}

/** Open issue ****************************************************************/

	.issue {
		border-color: #e05252;
		border-color: var(--issue-border);
		background: #fbe9e9;
		background: var(--issue-bg);
		color: black;
		color: var(--issue-text);
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		color: #831616;
		color: var(--issueheading-text);
	}
	/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
	   or use class="marker" to mark up the issue number in source. */

/** Example *******************************************************************/

	.example {
		border-color: #e0cb52;
		border-color: var(--example-border);
		background: #fcfaee;
		background: var(--example-bg);
		color: black;
		color: var(--example-text);
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		color: #574b0f;
		color: var(--exampleheading-text);
	}
	/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
	   or use class="marker" to mark up the example number in source. */

/** Non-normative Note ********************************************************/

	.note {
		border-color: #52e052;
		border-color: var(--note-border);
		background: #e9fbe9;
		background: var(--note-bg);
		color: black;
		color: var(--note-text);
		overflow: auto;
	}

	.note::before, .note > .marker,
	details.note > summary {
		color: hsl(120, 70%, 30%);
		color: var(--noteheading-text);
	}
	/* Add .note::before { content: "Note "; } for autogen label,
	   or use class="marker" to mark up the label in source. */

	details.note[open] > summary {
		border-bottom: 1px silver solid;
		border-bottom: 1px var(--notesummary-underline) solid;
	}

/** Assertion Box *************************************************************/
	/*  for assertions in algorithms */

	.assertion {
		border-color: #AAA;
		border-color: var(--assertion-border);
		background: #EEE;
		background: var(--assertion-bg);
		color: black;
		color: var(--assertion-text);
	}

/** Advisement Box ************************************************************/
	/*  for attention-grabbing normative statements */

	.advisement {
		border-color: orange;
		border-color: var(--advisement-border);
		border-style: none solid;
		background: #fec;
		background: var(--advisement-bg);
		color: black;
		color: var(--advisement-text);
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement::before, .advisement > .marker {
		color: #b35f00;
		color: var(--advisementheading-text);
	}

/** Spec Obsoletion Notice ****************************************************/
	/* obnoxious obsoletion notice for older/abandoned specs. */

	details {
		display: block;
	}
	summary {
		font-weight: bolder;
	}

	.annoying-warning:not(details),
	details.annoying-warning:not([open]) > summary,
	details.annoying-warning[open] {
		background: hsla(40,100%,50%,0.95);
		background: var(--warning-bg);
		color: black;
		color: var(--warning-text);
		padding: .75em 1em;
		border: red;
		border: var(--warning-border);
		border-style: solid none;
		box-shadow: 0 2px 8px black;
		text-align: center;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

	@media not print {
		details.annoying-warning[open] {
			position: fixed;
			left: 0;
			right: 0;
			bottom: 2em;
			z-index: 1000;
		}
	}

	details.annoying-warning:not([open]) > summary {
		text-align: center;
	}

/** Entity Definition Boxes ***************************************************/

	.def {
		padding: .5em 1em;
		background: #def;
		background: var(--def-bg);
		margin: 1.2em 0;
		border-left: 0.5em solid #8ccbf2;
		border-left: 0.5em solid var(--def-border);
		color: black;
		color: var(--def-text);
	}

/******************************************************************************/
/*                                    Tables                                  */
/******************************************************************************/

	th, td {
		text-align: left;
		text-align: start;
	}

/** Property/Descriptor Definition Tables *************************************/

	table.def {
		/* inherits .def box styling, see above */
		width: 100%;
		border-spacing: 0;
	}

	table.def td,
	table.def th {
		padding: 0.5em;
		vertical-align: baseline;
		border-bottom: 1px solid #bbd7e9;
		border-bottom: 1px solid var(--defrow-border);
	}

	table.def > tbody > tr:last-child th,
	table.def > tbody > tr:last-child td {
		border-bottom: 0;
	}

	table.def th {
		font-style: italic;
		font-weight: normal;
		padding-left: 1em;
		width: 3em;
	}

	/* For when values are extra-complex and need formatting for readability */
	table td.pre {
		white-space: pre-wrap;
	}

	/* A footnote at the bottom of a def table */
	table.def td.footnote {
		padding-top: 0.6em;
	}
	table.def td.footnote::before {
		content: " ";
		display: block;
		height: 0.6em;
		width: 4em;
		border-top: thin solid;
	}

/** Data tables (and properly marked-up index tables) *************************/
	/*
		 <table class="data"> highlights structural relationships in a table
		 when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)

		 Use class="complex data" for particularly complicated tables --
		 (This will draw more lines: busier, but clearer.)

		 Use class="long" on table cells with paragraph-like contents
		 (This will adjust text alignment accordingly.)
		 Alternately use class="longlastcol" on tables, to have the last column assume "long".
	*/

	table {
		word-wrap: normal;
		overflow-wrap: normal;
		hyphens: manual;
	}

	table.data,
	table.index {
		margin: 1em auto;
		border-collapse: collapse;
		border: hidden;
		width: 100%;
	}
	table.data caption,
	table.index caption {
		max-width: 50em;
		margin: 0 auto 1em;
	}

	table.data td,  table.data th,
	table.index td, table.index th {
		padding: 0.5em 1em;
		border-width: 1px;
		border-color: silver;
		border-color: var(--datacell-border);
		border-top-style: solid;
	}

	table.data thead td:empty {
		padding: 0;
		border: 0;
	}

	table.data  thead,
	table.index thead,
	table.data  tbody,
	table.index tbody {
		border-bottom: 2px solid;
	}

	table.data colgroup,
	table.index colgroup {
		border-left: 2px solid;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		border-right: 2px solid;
		border-top: 1px solid silver;
		border-top: 1px solid var(--datacell-border);
		padding-right: 1em;
	}

	table.data th[colspan],
	table.data td[colspan] {
		text-align: center;
	}

	table.complex.data th,
	table.complex.data td {
		border: 1px solid silver;
		border: 1px solid var(--datacell-border);
		text-align: center;
	}

	table.data.longlastcol td:last-child,
	table.data td.long {
		vertical-align: baseline;
		text-align: left;
	}

	table.data img {
		vertical-align: middle;
	}


/*
Alternate table alignment rules

	table.data,
	table.index {
		text-align: center;
	}

	table.data  thead th[scope="row"],
	table.index thead th[scope="row"] {
		text-align: right;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		text-align: right;
	}

Possible extra rowspan handling

	table.data  tbody th[rowspan]:not([rowspan='1']),
	table.index tbody th[rowspan]:not([rowspan='1']),
	table.data  tbody td[rowspan]:not([rowspan='1']),
	table.index tbody td[rowspan]:not([rowspan='1']) {
		border-left: 1px solid silver;
	}

	table.data  tbody th[rowspan]:first-child,
	table.index tbody th[rowspan]:first-child,
	table.data  tbody td[rowspan]:first-child,
	table.index tbody td[rowspan]:first-child{
		border-left: 0;
		border-right: 1px solid silver;
	}
*/

/******************************************************************************/
/*                                  Indices                                   */
/******************************************************************************/


/** Table of Contents *********************************************************/

	.toc a {
		/* More spacing; use padding to make it part of the click target. */
		padding-top: 0.1rem;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Reverse color scheme */
		color: black;
		color: var(--toclink-text);
		border-color: #3980b5;
		border-color: var(--toclink-underline);
	}
	.toc a:visited {
		color: black;
		color: var(--toclink-visited-text);
		border-color: #054572;
		border-color: var(--toclink-visited-underline);
	}
	.toc a:not(:focus):not(:hover) {
		/* Allow colors to cascade through from link styling */
		border-bottom-color: transparent;
	}

	.toc, .toc ol, .toc ul, .toc li {
		list-style: none; /* Numbers must be inlined into source */
		/* because generated content isn't search/selectable and markers can't do multilevel yet */
		margin:  0;
		padding: 0;
		line-height: 1.1rem; /* consistent spacing */
	}

	/* ToC not indented until third level, but font style & margins show hierarchy */
	.toc > li             { font-weight: bold;   }
	.toc > li li          { font-weight: normal; }
	.toc > li li li       { font-size:   95%;    }
	.toc > li li li li    { font-size:   90%;    }
	.toc > li li li li .secno { font-size: 85%; }
	.toc > li li li li li { font-size:   85%;    }
	.toc > li li li li li .secno { font-size: 100%; }

	/* @supports not (display:grid) { */
		.toc > li             { margin: 1.5rem 0;    }
		.toc > li li          { margin: 0.3rem 0;    }
		.toc > li li li       { margin-left: 2rem;   }

		/* Section numbers in a column of their own */
		.toc .secno {
			float: left;
			width: 4rem;
			white-space: nowrap;
		}

		.toc li {
			clear: both;
		}

		:not(li) > .toc              { margin-left:  5rem; }
		.toc .secno                  { margin-left: -5rem; }
		.toc > li li li .secno       { margin-left: -7rem; }
		.toc > li li li li .secno    { margin-left: -9rem; }
		.toc > li li li li li .secno { margin-left: -11rem; }

		/* Tighten up indentation in narrow ToCs */
		@media (max-width: 30em) {
			:not(li) > .toc              { margin-left:  4rem; }
			.toc .secno                  { margin-left: -4rem; }
			.toc > li li li              { margin-left:  1rem; }
			.toc > li li li .secno       { margin-left: -5rem; }
			.toc > li li li li .secno    { margin-left: -6rem; }
			.toc > li li li li li .secno { margin-left: -7rem; }
		}
		/* Loosen it on wide screens */
		@media screen and (min-width: 78em) {
			body:not(.toc-inline) :not(li) > .toc              { margin-left:  4rem; }
			body:not(.toc-inline) .toc .secno                  { margin-left: -4rem; }
			body:not(.toc-inline) .toc > li li li              { margin-left:  1rem; }
			body:not(.toc-inline) .toc > li li li .secno       { margin-left: -5rem; }
			body:not(.toc-inline) .toc > li li li li .secno    { margin-left: -6rem; }
			body:not(.toc-inline) .toc > li li li li li .secno { margin-left: -7rem; }
	}
	/* } */

	@supports (display:grid) and (display:contents) {
		/* Use #toc over .toc to override non-@supports rules. */
		#toc {
			display: grid;
			align-content: start;
			grid-template-columns: auto 1fr;
			grid-column-gap: 1rem;
			column-gap: 1rem;
			grid-row-gap: .6rem;
			row-gap: .6rem;
		}
		#toc h2 {
			grid-column: 1 / -1;
			margin-bottom: 0;
		}
		#toc ol,
		#toc li,
		#toc a {
			display: contents;
			/* Switch <a> to subgrid when supported */
		}
		#toc span {
			margin: 0;
		}
		#toc > .toc > li > a > span {
			/* The spans of the top-level list,
			   comprising the first items of each top-level section. */
			margin-top: 1.1rem;
		}
		#toc#toc .secno { /* Ugh, need more specificity to override base.css */
			grid-column: 1;
			width: auto;
			margin-left: 0;
		}
		#toc .content {
			grid-column: 2;
			width: auto;
			margin-right: 1rem;
		}
		#toc .content:hover,
		#toc .content:focus {
			background: rgba(75%, 75%, 75%, .25);
			background: var(--a-hover-bg);
			border-bottom: 3px solid #054572;
			border-bottom: 3px solid var(--toclink-underline);
			margin-bottom: -3px;
		}
		#toc li li li .content {
			margin-left: 1rem;
		}
		#toc li li li li .content {
			margin-left: 2rem;
		}
	}


/** Index *********************************************************************/

	/* Index Lists: Layout */
	ul.index       { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
	ul.index li    { margin-left: 0; list-style: none; break-inside: avoid; }
	ul.index li li { margin-left: 1em }
	ul.index dl    { margin-top: 0; }
	ul.index dt    { margin: .2em 0 .2em 20px;}
	ul.index dd    { margin: .2em 0 .2em 40px;}
	/* Index Lists: Typography */
	ul.index ul,
	ul.index dl { font-size: smaller; }
	@media not print {
		ul.index li span:not(.dfn-paneled) {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
			color: var(--indexinfo-text);
		}
	}

/** Index Tables *****************************************************/
	/* See also the data table styling section, which this effectively subclasses */

	table.index {
		font-size: small;
		border-collapse: collapse;
		border-spacing: 0;
		text-align: left;
		margin: 1em 0;
	}

	table.index td,
	table.index th {
		padding: 0.4em;
	}

	table.index tr:hover td:not([rowspan]),
	table.index tr:hover th:not([rowspan]) {
		color: black;
		color: var(--indextable-hover-text);
		background: #f7f8f9;
		background: var(--indextable-hover-bg);
	}

	/* The link in the first column in the property table (formerly a TD) */
	table.index th:first-child a {
		font-weight: bold;
	}

/******************************************************************************/
/*                                    Print                                   */
/******************************************************************************/

	@media print {
		/* Pages have their own margins. */
		html {
			margin: 0;
		}
		/* Serif for print. */
		body {
			font-family: serif;
		}
	}
	@page {
		margin: 1.5cm 1.1cm;
	}



/******************************************************************************/
/*                             Overflow Control                               */
/******************************************************************************/

	.figure .caption, .sidefigure .caption, figcaption {
		/* in case figure is overlarge, limit caption to 50em */
		max-width: 50rem;
		margin-left: auto;
		margin-right: auto;
	}
	.overlarge {
		/* Magic to create good table positioning:
		   "content column" is 50ems wide at max; less on smaller screens.
		   Extra space (after ToC + content) is empty on the right.

		   1. When table < content column, centers table in column.
		   2. When content < table < available, left-aligns.
		   3. When table > available, fills available + scroll bar.
		*/
		display: grid;
		grid-template-columns: minmax(0, 50em);
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-right: calc(13px + 26.5rem - 50vw);
			max-width: none;
		}
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) .overlarge {
			/* 30.5em body padding 50em content area */
			margin-right: calc(40em - 50vw) !important;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) .overlarge {
			/* 4em html margin 30.5em body padding 50em content area */
			margin-right: calc(84.5em - 100vw) !important;
		}
	}

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			 * http://lea.verou.me/2012/04/background-attachment-local/
			 *
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
			            top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
			            top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
<style type="text/css">
    table, th, td {
      border: 1px solid black;
      border-collapse: collapse;
      vertical-align: top;
    }
    th, td {
      border-left: none;
      border-right: none;
      padding: 0px 10px;
    }
    th {
      text-align: center;
    }

    del { background: #fcc; color: #000; text-decoration: line-through; }
    ins { background: #cfc; color: #000; }
    blockquote .highlight:not(.idl) { background: initial; margin: initial; padding: 0.5em }
    blockquote ul { background: inherit; }
    blockquote code.highlight:not(.idl) { padding: initial; }
    blockquote c-[a] { color: inherit; } /* Keyword.Declaration */
    blockquote c-[b] { color: inherit; } /* Keyword.Type */
    blockquote c-[c] { color: inherit; } /* Comment */
    blockquote c-[d] { color: inherit; } /* Comment.Multiline */
    blockquote c-[e] { color: inherit; } /* Name.Attribute */
    blockquote c-[f] { color: inherit; } /* Name.Tag */
    blockquote c-[g] { color: inherit; } /* Name.Variable */
    blockquote c-[k] { color: inherit; } /* Keyword */
    blockquote c-[l] { color: inherit; } /* Literal */
    blockquote c-[m] { color: inherit; } /* Literal.Number */
    blockquote c-[n] { color: inherit; } /* Name */
    blockquote c-[o] { color: inherit; } /* Operator */
    blockquote c-[p] { color: inherit; } /* Punctuation */
    blockquote c-[s] { color: inherit; } /* Literal.String */
    blockquote c-[t] { color: inherit; } /* Literal.String.Single */
    blockquote c-[u] { color: inherit; } /* Literal.String.Double */
    blockquote c-[cp] { color: inherit; } /* Comment.Preproc */
    blockquote c-[c1] { color: inherit; } /* Comment.Single */
    blockquote c-[cs] { color: inherit; } /* Comment.Special */
    blockquote c-[kc] { color: inherit; } /* Keyword.Constant */
    blockquote c-[kn] { color: inherit; } /* Keyword.Namespace */
    blockquote c-[kp] { color: inherit; } /* Keyword.Pseudo */
    blockquote c-[kr] { color: inherit; } /* Keyword.Reserved */
    blockquote c-[ld] { color: inherit; } /* Literal.Date */
    blockquote c-[nc] { color: inherit; } /* Name.Class */
    blockquote c-[no] { color: inherit; } /* Name.Constant */
    blockquote c-[nd] { color: inherit; } /* Name.Decorator */
    blockquote c-[ni] { color: inherit; } /* Name.Entity */
    blockquote c-[ne] { color: inherit; } /* Name.Exception */
    blockquote c-[nf] { color: inherit; } /* Name.Function */
    blockquote c-[nl] { color: inherit; } /* Name.Label */
    blockquote c-[nn] { color: inherit; } /* Name.Namespace */
    blockquote c-[py] { color: inherit; } /* Name.Property */
    blockquote c-[ow] { color: inherit; } /* Operator.Word */
    blockquote c-[mb] { color: inherit; } /* Literal.Number.Bin */
    blockquote c-[mf] { color: inherit; } /* Literal.Number.Float */
    blockquote c-[mh] { color: inherit; } /* Literal.Number.Hex */
    blockquote c-[mi] { color: inherit; } /* Literal.Number.Integer */
    blockquote c-[mo] { color: inherit; } /* Literal.Number.Oct */
    blockquote c-[sb] { color: inherit; } /* Literal.String.Backtick */
    blockquote c-[sc] { color: inherit; } /* Literal.String.Char */
    blockquote c-[sd] { color: inherit; } /* Literal.String.Doc */
    blockquote c-[se] { color: inherit; } /* Literal.String.Escape */
    blockquote c-[sh] { color: inherit; } /* Literal.String.Heredoc */
    blockquote c-[si] { color: inherit; } /* Literal.String.Interpol */
    blockquote c-[sx] { color: inherit; } /* Literal.String.Other */
    blockquote c-[sr] { color: inherit; } /* Literal.String.Regex */
    blockquote c-[ss] { color: inherit; } /* Literal.String.Symbol */
    blockquote c-[vc] { color: inherit; } /* Name.Variable.Class */
    blockquote c-[vg] { color: inherit; } /* Name.Variable.Global */
    blockquote c-[vi] { color: inherit; } /* Name.Variable.Instance */
    blockquote c-[il] { color: inherit; } /* Literal.Number.Integer.Long */
  </style>
  <meta content="Bikeshed version 89ebb6ab, updated Fri Oct 9 15:32:07 2020 -0700" name="generator">
  <link href="http://wg21.link/P2723" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="48598d1984f329ec439df21f7c46caab857292c7" name="document-revision">
<style>
table, th, td { border: 2px solid grey; }
</style>
<style>/* style-autolinks */

.css.css, .property.property, .descriptor.descriptor {
    color: var(--a-normal-text);
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

[data-link-type].production::before,
[data-link-type].production::after,
.prod [data-link-type]::before,
.prod [data-link-type]::after {
    content: "";
}

[data-link-type=element],
[data-link-type=element-attr] {
    font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
    font-size: .9em;
}
[data-link-type=element]::before { content: "<" }
[data-link-type=element]::after  { content: ">" }

[data-link-type=biblio] {
    white-space: pre;
}</style>
<style>/* style-colors */

/* Any --*-text not paired with a --*-bg is assumed to have a transparent bg */
html {
    color: black;
    color: var(--text);
    background-color: white;
    background-color: var(--bg);
}
:root {
    color-scheme: light dark;

    --text: black;
    --bg: white;

    --logo-bg: #1a5e9a;
    --logo-active-bg: #c00;
    --logo-text: white;

    --tocnav-normal-text: #707070;
    --tocnav-normal-bg: var(--bg);
    --tocnav-hover-text: var(--tocnav-normal-text);
    --tocnav-hover-bg: #f8f8f8;
    --tocnav-active-text: #c00;
    --tocnav-active-bg: var(--tocnav-normal-bg);

    --tocsidebar-text: var(--text);
    --tocsidebar-bg: #f7f8f9;
    --tocsidebar-shadow: rgba(0,0,0,.1);
    --tocsidebar-heading-text: hsla(203,20%,40%,.7);

    --toclink-text: var(--text);
    --toclink-underline: #3980b5;
    --toclink-visited-text: var(--toclink-text);
    --toclink-visited-underline: #054572;

    --heading-text: #005a9c;

    --hr-text: var(--text);

    --algo-border: #def;

    --del-text: red;
    --del-bg: transparent;
    --ins-text: #080;
    --ins-bg: transparent;

    --a-normal-text: #034575;
    --a-normal-underline: #707070;
    --a-visited-text: var(--a-normal-text);
    --a-visited-underline: #bbb;
    --a-hover-bg: rgba(75%, 75%, 75%, .25);
    --a-active-text: #c00;
    --a-active-underline: #c00;

    --blockquote-border: silver;
    --blockquote-bg: transparent;
    --blockquote-text: currentcolor;

    --issue-border: #e05252;
    --issue-bg: #fbe9e9;
    --issue-text: var(--text);
    --issueheading-text: #831616;

    --example-border: #e0cb52;
    --example-bg: #fcfaee;
    --example-text: var(--text);
    --exampleheading-text: #574b0f;

    --note-border: #52e052;
    --note-bg: #e9fbe9;
    --note-text: var(--text);
    --noteheading-text: hsl(120, 70%, 30%);
    --notesummary-underline: silver;

    --assertion-border: #aaa;
    --assertion-bg: #eee;
    --assertion-text: black;

    --advisement-border: orange;
    --advisement-bg: #fec;
    --advisement-text: var(--text);
    --advisementheading-text: #b35f00;

    --warning-border: red;
    --warning-bg: hsla(40,100%,50%,0.95);
    --warning-text: var(--text);

    --def-border: #8ccbf2;
    --def-bg: #def;
    --def-text: var(--text);
    --defrow-border: #bbd7e9;

    --datacell-border: silver;

    --indexinfo-text: #707070;

    --indextable-hover-text: black;
    --indextable-hover-bg: #f7f8f9;

    --outdatedspec-bg: rgba(0, 0, 0, .5);
    --outdatedspec-text: black;
    --outdated-bg: maroon;
    --outdated-text: white;
    --outdated-shadow: red;

    --editedrec-bg: darkorange;
}</style>
<style>/* style-counters */

body {
    counter-reset: example figure issue;
}
.issue {
    counter-increment: issue;
}
.issue:not(.no-marker)::before {
    content: "Issue " counter(issue);
}

.example {
    counter-increment: example;
}
.example:not(.no-marker)::before {
    content: "Example " counter(example);
}
.invalid.example:not(.no-marker)::before,
.illegal.example:not(.no-marker)::before {
    content: "Invalid Example" counter(example);
}

figcaption {
    counter-increment: figure;
}
figcaption:not(.no-marker)::before {
    content: "Figure " counter(figure) " ";
}</style>
<style>/* style-md-lists */

/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}</style>
<style>/* style-selflinks */

:root {
    --selflink-text: white;
    --selflink-bg: gray;
    --selflink-hover-text: black;
}
.heading, .issue, .note, .example, li, dt {
    position: relative;
}
a.self-link {
    position: absolute;
    top: 0;
    left: calc(-1 * (3.5rem - 26px));
    width: calc(3.5rem - 26px);
    height: 2em;
    text-align: center;
    border: none;
    transition: opacity .2s;
    opacity: .5;
}
a.self-link:hover {
    opacity: 1;
}
.heading > a.self-link {
    font-size: 83%;
}
li > a.self-link {
    left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
    top: auto;
    left: auto;
    opacity: 0;
    width: 1.5em;
    height: 1.5em;
    background: var(--selflink-bg);
    color: var(--selflink-text);
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: var(--selflink-hover-text);
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }
</style>
<style>/* style-syntax-highlighting */

code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }

.highlight:not(.idl) { background: #fdf6e3; }
c-[a] { color: #990055 } /* Keyword.Declaration */
c-[b] { color: #990055 } /* Keyword.Type */
c-[c] { color: #708090 } /* Comment */
c-[d] { color: #708090 } /* Comment.Multiline */
c-[e] { color: #0077aa } /* Name.Attribute */
c-[f] { color: #669900 } /* Name.Tag */
c-[g] { color: #222222 } /* Name.Variable */
c-[k] { color: #990055 } /* Keyword */
c-[l] { color: #000000 } /* Literal */
c-[m] { color: #000000 } /* Literal.Number */
c-[n] { color: #0077aa } /* Name */
c-[o] { color: #999999 } /* Operator */
c-[p] { color: #999999 } /* Punctuation */
c-[s] { color: #a67f59 } /* Literal.String */
c-[t] { color: #a67f59 } /* Literal.String.Single */
c-[u] { color: #a67f59 } /* Literal.String.Double */
c-[cp] { color: #708090 } /* Comment.Preproc */
c-[c1] { color: #708090 } /* Comment.Single */
c-[cs] { color: #708090 } /* Comment.Special */
c-[kc] { color: #990055 } /* Keyword.Constant */
c-[kn] { color: #990055 } /* Keyword.Namespace */
c-[kp] { color: #990055 } /* Keyword.Pseudo */
c-[kr] { color: #990055 } /* Keyword.Reserved */
c-[ld] { color: #000000 } /* Literal.Date */
c-[nc] { color: #0077aa } /* Name.Class */
c-[no] { color: #0077aa } /* Name.Constant */
c-[nd] { color: #0077aa } /* Name.Decorator */
c-[ni] { color: #0077aa } /* Name.Entity */
c-[ne] { color: #0077aa } /* Name.Exception */
c-[nf] { color: #0077aa } /* Name.Function */
c-[nl] { color: #0077aa } /* Name.Label */
c-[nn] { color: #0077aa } /* Name.Namespace */
c-[py] { color: #0077aa } /* Name.Property */
c-[ow] { color: #999999 } /* Operator.Word */
c-[mb] { color: #000000 } /* Literal.Number.Bin */
c-[mf] { color: #000000 } /* Literal.Number.Float */
c-[mh] { color: #000000 } /* Literal.Number.Hex */
c-[mi] { color: #000000 } /* Literal.Number.Integer */
c-[mo] { color: #000000 } /* Literal.Number.Oct */
c-[sb] { color: #a67f59 } /* Literal.String.Backtick */
c-[sc] { color: #a67f59 } /* Literal.String.Char */
c-[sd] { color: #a67f59 } /* Literal.String.Doc */
c-[se] { color: #a67f59 } /* Literal.String.Escape */
c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */
c-[si] { color: #a67f59 } /* Literal.String.Interpol */
c-[sx] { color: #a67f59 } /* Literal.String.Other */
c-[sr] { color: #a67f59 } /* Literal.String.Regex */
c-[ss] { color: #a67f59 } /* Literal.String.Symbol */
c-[vc] { color: #0077aa } /* Name.Variable.Class */
c-[vg] { color: #0077aa } /* Name.Variable.Global */
c-[vi] { color: #0077aa } /* Name.Variable.Instance */
c-[il] { color: #000000 } /* Literal.Number.Integer.Long */
</style>
<style>/* style-darkmode */

@media (prefers-color-scheme: dark) {
    :root {
        --text: #ddd;
        --bg: black;

        --logo-bg: #1a5e9a;
        --logo-active-bg: #c00;
        --logo-text: white;

        --tocnav-normal-text: #999;
        --tocnav-normal-bg: var(--bg);
        --tocnav-hover-text: var(--tocnav-normal-text);
        --tocnav-hover-bg: #080808;
        --tocnav-active-text: #f44;
        --tocnav-active-bg: var(--tocnav-normal-bg);

        --tocsidebar-text: var(--text);
        --tocsidebar-bg: #080808;
        --tocsidebar-shadow: rgba(255,255,255,.1);
        --tocsidebar-heading-text: hsla(203,20%,40%,.7);

        --toclink-text: var(--text);
        --toclink-underline: #6af;
        --toclink-visited-text: var(--toclink-text);
        --toclink-visited-underline: #054572;

        --heading-text: #8af;

        --hr-text: var(--text);

        --algo-border: #456;

        --del-text: #f44;
        --del-bg: transparent;
        --ins-text: #4a4;
        --ins-bg: transparent;

        --a-normal-text: #6af;
        --a-normal-underline: #555;
        --a-visited-text: var(--a-normal-text);
        --a-visited-underline: var(--a-normal-underline);
        --a-hover-bg: rgba(25%, 25%, 25%, .2);
        --a-active-text: #f44;
        --a-active-underline: var(--a-active-text);

        --borderedblock-bg: rgba(255, 255, 255, .05);

        --blockquote-border: silver;
        --blockquote-bg: var(--borderedblock-bg);
        --blockquote-text: currentcolor;

        --issue-border: #e05252;
        --issue-bg: var(--borderedblock-bg);
        --issue-text: var(--text);
        --issueheading-text: hsl(0deg, 70%, 70%);

        --example-border: hsl(50deg, 90%, 60%);
        --example-bg: var(--borderedblock-bg);
        --example-text: var(--text);
        --exampleheading-text: hsl(50deg, 70%, 70%);

        --note-border: hsl(120deg, 100%, 35%);
        --note-bg: var(--borderedblock-bg);
        --note-text: var(--text);
        --noteheading-text: hsl(120, 70%, 70%);
        --notesummary-underline: silver;

        --assertion-border: #444;
        --assertion-bg: var(--borderedblock-bg);
        --assertion-text: var(--text);

        --advisement-border: orange;
        --advisement-bg: #222218;
        --advisement-text: var(--text);
        --advisementheading-text: #f84;

        --warning-border: red;
        --warning-bg: hsla(40,100%,20%,0.95);
        --warning-text: var(--text);

        --def-border: #8ccbf2;
        --def-bg: #080818;
        --def-text: var(--text);
        --defrow-border: #136;

        --datacell-border: silver;

        --indexinfo-text: #aaa;

        --indextable-hover-text: var(--text);
        --indextable-hover-bg: #181818;

        --outdatedspec-bg: rgba(255, 255, 255, .5);
        --outdatedspec-text: black;
        --outdated-bg: maroon;
        --outdated-text: white;
        --outdated-shadow: red;

        --editedrec-bg: darkorange;
    }
    /* In case a transparent-bg image doesn't expect to be on a dark bg,
       which is quite common in practice... */
    img { background: white; }
}
@media (prefers-color-scheme: dark) {
    :root {
        --selflink-text: black;
        --selflink-bg: silver;
        --selflink-hover-text: white;
    }
}

@media (prefers-color-scheme: dark) {
    .highlight:not(.idl) { background: rgba(255, 255, 255, .05); }

    c-[a] { color: #d33682 } /* Keyword.Declaration */
    c-[b] { color: #d33682 } /* Keyword.Type */
    c-[c] { color: #2aa198 } /* Comment */
    c-[d] { color: #2aa198 } /* Comment.Multiline */
    c-[e] { color: #268bd2 } /* Name.Attribute */
    c-[f] { color: #b58900 } /* Name.Tag */
    c-[g] { color: #cb4b16 } /* Name.Variable */
    c-[k] { color: #d33682 } /* Keyword */
    c-[l] { color: #657b83 } /* Literal */
    c-[m] { color: #657b83 } /* Literal.Number */
    c-[n] { color: #268bd2 } /* Name */
    c-[o] { color: #657b83 } /* Operator */
    c-[p] { color: #657b83 } /* Punctuation */
    c-[s] { color: #6c71c4 } /* Literal.String */
    c-[t] { color: #6c71c4 } /* Literal.String.Single */
    c-[u] { color: #6c71c4 } /* Literal.String.Double */
    c-[ch] { color: #2aa198 } /* Comment.Hashbang */
    c-[cp] { color: #2aa198 } /* Comment.Preproc */
    c-[cpf] { color: #2aa198 } /* Comment.PreprocFile */
    c-[c1] { color: #2aa198 } /* Comment.Single */
    c-[cs] { color: #2aa198 } /* Comment.Special */
    c-[kc] { color: #d33682 } /* Keyword.Constant */
    c-[kn] { color: #d33682 } /* Keyword.Namespace */
    c-[kp] { color: #d33682 } /* Keyword.Pseudo */
    c-[kr] { color: #d33682 } /* Keyword.Reserved */
    c-[ld] { color: #657b83 } /* Literal.Date */
    c-[nc] { color: #268bd2 } /* Name.Class */
    c-[no] { color: #268bd2 } /* Name.Constant */
    c-[nd] { color: #268bd2 } /* Name.Decorator */
    c-[ni] { color: #268bd2 } /* Name.Entity */
    c-[ne] { color: #268bd2 } /* Name.Exception */
    c-[nf] { color: #268bd2 } /* Name.Function */
    c-[nl] { color: #268bd2 } /* Name.Label */
    c-[nn] { color: #268bd2 } /* Name.Namespace */
    c-[py] { color: #268bd2 } /* Name.Property */
    c-[ow] { color: #657b83 } /* Operator.Word */
    c-[mb] { color: #657b83 } /* Literal.Number.Bin */
    c-[mf] { color: #657b83 } /* Literal.Number.Float */
    c-[mh] { color: #657b83 } /* Literal.Number.Hex */
    c-[mi] { color: #657b83 } /* Literal.Number.Integer */
    c-[mo] { color: #657b83 } /* Literal.Number.Oct */
    c-[sa] { color: #6c71c4 } /* Literal.String.Affix */
    c-[sb] { color: #6c71c4 } /* Literal.String.Backtick */
    c-[sc] { color: #6c71c4 } /* Literal.String.Char */
    c-[dl] { color: #6c71c4 } /* Literal.String.Delimiter */
    c-[sd] { color: #6c71c4 } /* Literal.String.Doc */
    c-[se] { color: #6c71c4 } /* Literal.String.Escape */
    c-[sh] { color: #6c71c4 } /* Literal.String.Heredoc */
    c-[si] { color: #6c71c4 } /* Literal.String.Interpol */
    c-[sx] { color: #6c71c4 } /* Literal.String.Other */
    c-[sr] { color: #6c71c4 } /* Literal.String.Regex */
    c-[ss] { color: #6c71c4 } /* Literal.String.Symbol */
    c-[fm] { color: #268bd2 } /* Name.Function.Magic */
    c-[vc] { color: #cb4b16 } /* Name.Variable.Class */
    c-[vg] { color: #cb4b16 } /* Name.Variable.Global */
    c-[vi] { color: #cb4b16 } /* Name.Variable.Instance */
    c-[vm] { color: #cb4b16 } /* Name.Variable.Magic */
    c-[il] { color: #657b83 } /* Literal.Number.Integer.Long */
}
</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P2723R1<br>Zero-initialize objects of automatic storage duration</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2023-01-15">2023-01-15</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="http://wg21.link/P2723">http://wg21.link/P2723</a>
     <dt class="editor">Author:
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:cxx@jfbastien.com">JF Bastien</a> (<span class="p-org org">Woven Planet</span>)
     <dt>Audience:
     <dd>EWG, SG12, SG22
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
     <dt>Source:
     <dd><a href="https://github.com/jfbastien/papers/blob/master/source/P2723r1.bs">github.com/jfbastien/papers/blob/master/source/P2723r1.bs</a>
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li><a href="#summary"><span class="secno">1</span> <span class="content">Summary</span></a>
    <li>
     <a href="#out-out"><span class="secno">2</span> <span class="content">Opting out</span></a>
     <ol class="toc">
      <li><a href="#attribute"><span class="secno">2.1</span> <span class="content"><code class="highlight"><c- p>[[</c-><c- n>uninitialized</c-><c- p>]]</c-></code> attribute</span></a>
      <li><a href="#void"><span class="secno">2.2</span> <span class="content"><code class="highlight"><c- b>void</c-></code> keyword</span></a>
      <li><a href="#std-uninitialized"><span class="secno">2.3</span> <span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>uninitialized</c-></code> library type</span></a>
      <li><a href="#weirdo"><span class="secno">2.4</span> <span class="content">Weird Idiom</span></a>
      <li><a href="#tooling"><span class="secno">2.5</span> <span class="content">Tooling</span></a>
     </ol>
    <li>
     <a href="#security"><span class="secno">3</span> <span class="content">Security details</span></a>
     <ol class="toc">
      <li><a href="#ub"><span class="secno">3.1</span> <span class="content">Undefined Behavior</span></a>
      <li><a href="#oops"><span class="secno">3.2</span> <span class="content">Compiler Optimizations</span></a>
      <li><a href="#examples"><span class="secno">3.3</span> <span class="content">Examples</span></a>
      <li><a href="#security-says"><span class="secno">3.4</span> <span class="content">Security Experts</span></a>
      <li><a href="#real-world"><span class="secno">3.5</span> <span class="content">In the Real World</span></a>
     </ol>
    <li>
     <a href="#alt"><span class="secno">4</span> <span class="content">Alternatives</span></a>
     <ol class="toc">
      <li><a href="#tools"><span class="secno">4.1</span> <span class="content">Tooling</span></a>
      <li><a href="#try-harder"><span class="secno">4.2</span> <span class="content">Trying harder</span></a>
      <li><a href="#Werror"><span class="secno">4.3</span> <span class="content"><code class="highlight"><c- o>-</c-><c- n>Werror</c-><c- o>=</c-><c- n>uninitialized</c-></code></span></a>
      <li><a href="#definitive"><span class="secno">4.4</span> <span class="content">Definitive initialization</span></a>
      <li><a href="#value-init"><span class="secno">4.5</span> <span class="content">Value initialization</span></a>
      <li><a href="#fixit"><span class="secno">4.6</span> <span class="content">Fixing initialization</span></a>
      <li><a href="#do-nothing"><span class="secno">4.7</span> <span class="content">Do nothing</span></a>
      <li><a href="#ffff"><span class="secno">4.8</span> <span class="content">Other values</span></a>
      <li><a href="#impl-def"><span class="secno">4.9</span> <span class="content">Implementation defined</span></a>
      <li><a href="#hybrid"><span class="secno">4.10</span> <span class="content">Hybrid approach</span></a>
      <li><a href="#overwrite"><span class="secno">4.11</span> <span class="content">Overwrite</span></a>
      <li><a href="#rust-ub"><span class="secno">4.12</span> <span class="content">Rust <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>uninitialized</c-></code></span></a>
      <li><a href="#wobble"><span class="secno">4.13</span> <span class="content">Wobbly bits</span></a>
      <li>
       <a href="#🧙"><span class="secno">4.14</span> <span class="content">New Word of Power</span></a>
       <ol class="toc">
        <li><a href="#to-err-is-human"><span class="secno">4.14.1</span> <span class="content">Erroneous Behavior</span></a>
        <li><a href="#words"><span class="secno">4.14.2</span> <span class="content">Other Words</span></a>
       </ol>
     </ol>
    <li><a href="#perf"><span class="secno">5</span> <span class="content">Performance</span></a>
    <li><a href="#caveats"><span class="secno">6</span> <span class="content">Caveats</span></a>
    <li><a href="#word"><span class="secno">7</span> <span class="content">Wording</span></a>
    <li><a href="#feedback"><span class="secno">8</span> <span class="content">Feedback</span></a>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="summary"><span class="secno">1. </span><span class="content">Summary</span><a class="self-link" href="#summary"></a></h2>
   <p>Reading uninitialized values is undefined behavior which leads to well-known
security issues <a data-link-type="biblio" href="#biblio-cwe-457">[CWE-457]</a>, from information leaks to attacker-controlled
values being used to control execution, leading to an exploit. This can occur
when:</p>
   <ul>
    <li data-md>
     <p>The compiler re-uses stack slots, and a value is used uninitialized;</p>
    <li data-md>
     <p>The compiler re-uses a register, and a value is used uninitialized;</p>
    <li data-md>
     <p>Stack structs / arrays / unions with padding are copied; and</p>
    <li data-md>
     <p>A heap-allocated value isn’t initialized before being used.</p>
   </ul>
   <p>This proposal only addresses the above issues when they occur for automatic
storage duration objects (on the stack). The proposal does not tackle objects
with dynamic object duration. Objects with static or thread local duration are
not problematic because they are already zero-initialized if they cannot be
constant initialized, even if they are non-trivial and have a constructor
execute after this initialization.</p>
<pre class="highlight"><code class="highlight"><c- k><c- k>static</c-></c-> <c- b><c- b>char</c-></c-> <c- n><c- n>global</c-></c-><c- p><c- p>[</c-></c-><c- mi><c- mi>128</c-></c-><c- p><c- p>];</c-></c->            <c- c1><c- c1>// already zero-initialized</c-></c->
<c- k><c- k>thread_local</c-></c-> <c- b><c- b>int</c-></c-> <c- n><c- n>thread_state</c-></c-><c- p><c- p>;</c-></c->      <c- c1><c- c1>// already zero-initialized</c-></c->

<c- b><c- b>int</c-></c-> <c- nf><c- nf>main</c-></c-><c- p><c- p>()</c-></c-> <c- p><c- p>{</c-></c->
  <c- b><c- b>char</c-></c-> <c- n><c- n>buffer</c-></c-><c- p><c- p>[</c-></c-><c- mi><c- mi>128</c-></c-><c- p><c- p>];</c-></c->                 <c- c1><c- c1>// not zero-initialized before this proposal</c-></c->
  
  <c- k><c- k>struct</c-></c-> <c- p><c- p>{</c-></c->
    <c- b><c- b>char</c-></c-> <c- n><c- n>type</c-></c-><c- p><c- p>;</c-></c->                      <c- c1><c- c1>// field zero-initialized with this proposal</c-></c->
    <c- c1><c- c1>// 3 byte padding on most architectures, zero-initialized with this proposal</c-></c->
    <c- b><c- b>int</c-></c-> <c- n><c- n>payload</c-></c-><c- p><c- p>;</c-></c->                    <c- c1><c- c1>// field zero-initialized with this proposal</c-></c->
  <c- p><c- p>}</c-></c-> <c- n><c- n>padded</c-></c-><c- p><c- p>;</c-></c->
  
  <c- k><c- k>struct</c-></c-> <c- p><c- p>{</c-></c->
    <c- b><c- b>char</c-></c-> <c- n><c- n>buf</c-></c-><c- p><c- p>[</c-></c-><c- mi><c- mi>3</c-></c-><c- p><c- p>];</c-></c->
    <c- c1><c- c1>// 1 byte tail padding on most architectures, zero-initialized with this proposal</c-></c->
  <c- p><c- p>}</c-></c-> <c- n><c- n>tails</c-></c-><c- p><c- p>[</c-></c-><c- mi><c- mi>2</c-></c-><c- p><c- p>];</c-></c->

  <c- k><c- k>union</c-></c-> <c- p><c- p>{</c-></c->
    <c- b><c- b>char</c-></c-> <c- n><c- n>small</c-></c-><c- p><c- p>;</c-></c->
    <c- b><c- b>int</c-></c-> <c- n><c- n>big</c-></c-><c- p><c- p>;</c-></c->
  <c- p><c- p>}</c-></c-> <c- n><c- n>lopsided</c-></c-> <c- o><c- o>=</c-></c-> <c- sc><c- sc>'?'</c-></c-><c- p><c- p>;</c-></c->                 <c- c1><c- c1>// padding zero-initialized with this proposal</c-></c->

  <c- b><c- b>size_t</c-></c-> <c- n><c- n>size</c-></c-> <c- o><c- o>=</c-></c-> <c- n><c- n>getSize</c-></c-><c- p><c- p>();</c-></c->
  <c- b><c- b>char</c-></c-> <c- n><c- n>vla</c-></c-><c- p><c- p>[</c-></c-><c- n><c- n>size</c-></c-><c- p><c- p>];</c-></c->                   <c- c1><c- c1>// in C code, VLAs are zero-initialized with this proposal</c-></c->
                                    <c- c1><c- c1>// C++ pretends that VLAs don’t exist</c-></c->

  <c- b><c- b>void</c-></c-> <c- o><c- o>*</c-></c-><c- n><c- n>allocated</c-></c-> <c- o><c- o>=</c-></c-> <c- n><c- n>alloca</c-></c-><c- p><c- p>(</c-></c-><c- n><c- n>size</c-></c-><c- p><c- p>);</c-></c->   <c- c1><c- c1>// alloca results are zero-initialized with this proposal</c-></c->
                                    <c- c1><c- c1>// alloca is a common extension</c-></c->
  
  <c- b><c- b>char</c-></c-> <c- o><c- o>*</c-></c-><c- n><c- n>allocated</c-></c-> <c- o><c- o>=</c-></c-> <c- n><c- n>malloc</c-></c-><c- p><c- p>(</c-></c-><c- mi><c- mi>128</c-></c-><c- p><c- p>);</c-></c->    <c- c1><c- c1>// unchanged</c-></c->
  <c- b><c- b>int</c-></c-> <c- o><c- o>*</c-></c-><c- n><c- n>new_int</c-></c-> <c- o><c- o>=</c-></c-> <c- k><c- k>new</c-></c-> <c- b><c- b>int</c-></c-><c- p><c- p>;</c-></c->           <c- c1><c- c1>// unchanged</c-></c->
  <c- b><c- b>char</c-></c-> <c- o><c- o>*</c-></c-><c- n><c- n>new_arr</c-></c-> <c- o><c- o>=</c-></c-> <c- k><c- k>new</c-></c-> <c- b><c- b>char</c-></c-><c- p><c- p>[</c-></c-><c- mi><c- mi>128</c-></c-><c- p><c- p>];</c-></c->    <c- c1><c- c1>// unchanged</c-></c->
<c- p><c- p>}</c-></c->
</code></pre>
   <p>This proposal therefore transforms some runtime undefined behavior into
well-defined behavior.</p>
   <p>Adopting this change would mitigate or extinguish around 10% of exploits against
security-relevant codebases (see numbers from <a data-link-type="biblio" href="#biblio-androidsec">[AndroidSec]</a> and <a data-link-type="biblio" href="#biblio-initall">[InitAll]</a> for
a representative sample, or <a data-link-type="biblio" href="#biblio-kcc">[KCC]</a> for a long list).</p>
   <p>We propose to zero-initialize all objects of automatic storage duration, making
C++ safer by default.</p>
   <p>This was implemented as an opt-in compiler flag in 2018 for LLVM <a data-link-type="biblio" href="#biblio-llvmreview">[LLVMReview]</a> and MSVC <a data-link-type="biblio" href="#biblio-winkernel">[WinKernel]</a>, and 2021 in for GCC <a data-link-type="biblio" href="#biblio-gccreview">[GCCReview]</a>. Since then it has
been deployed to:</p>
   <ul>
    <li data-md>
     <p>The OS of every desktop, laptop, and smartphone that you own;</p>
    <li data-md>
     <p>The web browser you’re using to read this paper;</p>
    <li data-md>
     <p>Many kernel extensions and userspace program in your laptop and smartphone; and</p>
    <li data-md>
     <p>Likely to your favorite videogame console.</p>
   </ul>
   <p>Unless of course you like esoteric devices. You can <a href="https://github.com/search?q=ftrivial-auto-var-init&amp;type=code">look for uses on websites such as GitHub</a>.</p>
   <p>The above codebases contain many millions of lines of code of C, C++,
Objective-C, and Objective-C++.</p>
   <p>The performance impact is negligible (less that 0.5% regression) to slightly
positive (that is, some code gets <em>faster</em> by up to 1%). The code size impact
is negligible (smaller than 0.5%). Compile-time regressions are negligible. Were
overheads to matter for particular coding patterns, compilers would be able to
obviate most of them.</p>
   <p>The only significant performance/code regressions are when code has very large
automatic storage duration objects. We provide an attribute to opt-out of
zero-initialization of objects of automatic storage duration. We then expect
that programmer can audit their code for this attribute, and ensure that the
unsafe subset of C++ is used in a safe manner.</p>
   <p>This change was not possible 30 years ago because optimizations simply were not
as good as they are today, and the costs were too high. The costs are now
negligible. We provide details in <a href="#perf">§ 5 Performance</a>.</p>
   <p>Overall, this proposal is a targeted fix which stands on its own, but should be
considered as part of a wider push for type and resource safe C++ such as in <a data-link-type="biblio" href="#biblio-p2687r0">[P2687r0]</a>.</p>
   <h2 class="heading settled" data-level="2" id="out-out"><span class="secno">2. </span><span class="content">Opting out</span><a class="self-link" href="#out-out"></a></h2>
   <h3 class="heading settled" data-level="2.1" id="attribute"><span class="secno">2.1. </span><span class="content"><code class="highlight"><c- p>[[</c-><c- n>uninitialized</c-><c- p>]]</c-></code> attribute</span><a class="self-link" href="#attribute"></a></h3>
   <p>In deploying this scheme, we’ve found that some codebases see unacceptable
regressions because they allocate large values on the stack and see performance
/ size regressions. We therefore propose standardizing an attribute which
denotes intent, <code class="highlight"><c- p>[[</c-><c- n>uninitialized</c-><c- p>]]</c-></code>. When put on automatic variables, no
initialization is performed. The programmer is then responsible for what happens
because they are back to C++23 behavior. This makes C++ safe by default for this
class of bugs, and provides an escape hatch when the safety is too onerous.</p>
   <p>An <code class="highlight"><c- p>[[</c-><c- n>uninitialized</c-><c- p>]]</c-></code> attribute was proposed in <a data-link-type="biblio" href="#biblio-p0632r0">[P0632r0]</a>.</p>
   <h3 class="heading settled" data-level="2.2" id="void"><span class="secno">2.2. </span><span class="content"><code class="highlight"><c- b>void</c-></code> keyword</span><a class="self-link" href="#void"></a></h3>
   <p>An alternative for the <code class="highlight"><c- p>[[</c-><c- n>uninitialized</c-><c- p>]]</c-></code> attribute is to use a keyword. We can
argue about which keyword is right. However, maybe through <a data-link-type="biblio" href="#biblio-p0146r1">[P0146r1]</a>, we’ll
eventually agree that <code class="highlight"><c- b>void</c-></code> is the right name for "This variable is not a
variable of honor... no highly esteemed deed is commemorated here... nothing
valued is here." This approach meshes well with a definitive initialization
approach because we would keep the semantics of "no value was intended on this
variable".</p>
   <h3 class="heading settled" data-level="2.3" id="std-uninitialized"><span class="secno">2.3. </span><span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>uninitialized</c-></code> library type</span><a class="self-link" href="#std-uninitialized"></a></h3>
   <p>Keywords are distasteful to some people, and some other people would rather have
a named type that they can overload on. For these folks, we might instead
consider a magical monostate standard library type name <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>uninitialized</c-></code>.
Magical monostate standard library types are distateful to some people, who will
get to argue for a keyword as above. This type could them be used in a variety
of interesting manners:</p>
<pre class="highlight"><code class="highlight"><c- b><c- b>int</c-></c-> <c- n><c- n>a</c-></c-> <c- o><c- o>=</c-></c-> <c- n><c- n>std</c-></c-><c- o><c- o>::</c-></c-><c- n><c- n>uninitialized</c-></c-><c- p><c- p>;</c-></c->
<c- b><c- b>int</c-></c-><c- o><c- o>*</c-></c-> <c- n><c- n>b</c-></c-> <c- o><c- o>=</c-></c-> <c- k><c- k>new</c-></c-> <c- b><c- b>int</c-></c-><c- p><c- p>(</c-></c-><c- n><c- n>std</c-></c-><c- o><c- o>::</c-></c-><c- n><c- n>uninitialized</c-></c-><c- p><c- p>);</c-></c->
<c- k><c- k>auto</c-></c-> <c- n><c- n>c</c-></c-> <c- o><c- o>=</c-></c-> <c- n><c- n>std</c-></c-><c- o><c- o>::</c-></c-><c- n><c- n>make_unique</c-></c-><int><c- p><c- p>(</c-></c-><c- n><c- n>std</c-></c-><c- o><c- o>::</c-></c-><c- n><c- n>uninitialized</c-></c-><c- p><c- p>);</c-></c->
</int></code></pre>
   <h3 class="heading settled" data-level="2.4" id="weirdo"><span class="secno">2.4. </span><span class="content">Weird Idiom</span><a class="self-link" href="#weirdo"></a></h3>
   <p>An idiom that is sometimes used to denote "uninitialized on purpose" is <code class="highlight"><c- b>int</c-> <c- n>value</c-> <c- o>=</c-> <c- n>value</c-><c- p>;</c-></code>. This is confusing and weird, but people like to
bring it up. Let’s agree to not.</p>
   <h3 class="heading settled" data-level="2.5" id="tooling"><span class="secno">2.5. </span><span class="content">Tooling</span><a class="self-link" href="#tooling"></a></h3>
   <p>As a quality of implementation tool, and to ease transitions, some
implementations might choose to diagnose on large stack values that might
benefit from this attribute. We caution implementations to avoid doing so in
their front-end, but rather to do this as a post-optimization annotation to
reduce noise. This was done in LLVM <a data-link-type="biblio" href="#biblio-autoinitsummary">[AutoInitSummary]</a>.</p>
   <h2 class="heading settled" data-level="3" id="security"><span class="secno">3. </span><span class="content">Security details</span><a class="self-link" href="#security"></a></h2>
   <p>What exactly is the security issues?</p>
   <h3 class="heading settled" data-level="3.1" id="ub"><span class="secno">3.1. </span><span class="content">Undefined Behavior</span><a class="self-link" href="#ub"></a></h3>
   <p>Currently, uninitialized stack variables are Undefined Behavior if they are used
(it is fine to copy them around, but not to use them). The typical outcome is
that the program reads stale stack or register values, that is whatever previous
value happened to be compiled to reside in the same stack slot or register. This
leads to bugs. Here are the potential outcomes:</p>
   <ul>
    <li data-md>
     <p><em>Benign</em>: in the best case the program causes an unexpected result.</p>
    <li data-md>
     <p><em>Exploit</em>: in the worst case it leads to an exploit. There are three outcomes that can lead to an exploit:</p>
    <li data-md>
     <p><em>Read primitive</em>: this exploit could be formed from reading leaked secrets that reside on the stack or in registers, and using this information to exploit another bug. For example, leaking an important address to defeat ASLR.</p>
    <li data-md>
     <p><em>Write primitive</em>: an uninitialized value is used to perform a write to an arbitrary address. Such a write can be transformed into an execute primitive. For example a stack slot is used on a particular execution path to determine the address of a write. The attack can control the previous stack slot’s content, and therefore control where the write occurs. Similarly, an attacker could control which value is written, but not where it is written.</p>
    <li data-md>
     <p><em>Execute primitive</em>: an uninitialized value is used to call a function.</p>
   </ul>
   <h3 class="heading settled" data-level="3.2" id="oops"><span class="secno">3.2. </span><span class="content">Compiler Optimizations</span><a class="self-link" href="#oops"></a></h3>
   <p>Compilers are also allowed to assume that programmers don’t do silly things like
this, and optimize assuming code that would read uninitialized state is never
reached. Programmers rarely find it hilarious when compilers do this type of
thing, but exploit writers might rejoice.</p>
   <h3 class="heading settled" data-level="3.3" id="examples"><span class="secno">3.3. </span><span class="content">Examples</span><a class="self-link" href="#examples"></a></h3>
   <p>Here are a few examples:</p>
<pre class="highlight"><code class="highlight"><c- b><c- b>int</c-></c-> <c- nf><c- nf>get_hw_address</c-></c-><c- p><c- p>(</c-></c-><c- k><c- k>struct</c-></c-> <c- n><c- n>device</c-></c-> <c- o><c- o>*</c-></c-><c- n><c- n>dev</c-></c-><c- p><c- p>,</c-></c-> <c- k><c- k>struct</c-></c-> <c- n><c- n>user</c-></c-> <c- o><c- o>*</c-></c-><c- n><c- n>usr</c-></c-><c- p><c- p>)</c-></c-> <c- p><c- p>{</c-></c->
  <c- b><c- b>unsigned</c-></c-> <c- b><c- b>char</c-></c-> <c- n><c- n>addr</c-></c-><c- p><c- p>[</c-></c-><c- n><c- n>MAX_ADDR_LEN</c-></c-><c- p><c- p>];</c-></c->         <c- c1><c- c1>// leak this memory 😢</c-></c->
  
  <c- k><c- k>if</c-></c-> <c- p><c- p>(</c-></c-><c- o><c- o>!</c-></c-><c- n><c- n>dev</c-></c-><c- o><c- o>-></c-></c-><c- n><c- n>has_address</c-></c-><c- p><c- p>)</c-></c->
    <c- k><c- k>return</c-></c-> <c- o><c- o>-</c-></c-><c- n><c- n>EOPNOTSUPP</c-></c-><c- p><c- p>;</c-></c->
    
  <c- n><c- n>dev</c-></c-><c- o><c- o>-></c-></c-><c- n><c- n>get_hw_address</c-></c-><c- p><c- p>(</c-></c-><c- n><c- n>addr</c-></c-><c- p><c- p>);</c-></c->                <c- c1><c- c1>// if this doesn’t fill addr</c-></c->
  <c- k><c- k>return</c-></c-> <c- n><c- n>copy_out</c-></c-><c- p><c- p>(</c-></c-><c- n><c- n>usr</c-></c-><c- p><c- p>,</c-></c-> <c- n><c- n>addr</c-></c-><c- p><c- p>,</c-></c-> <c- k><c- k>sizeof</c-></c-><c- p><c- p>(</c-></c-><c- n><c- n>addr</c-></c-><c- p><c- p>));</c-></c-> <c- c1><c- c1>// copies all</c-></c->
<c- p><c- p>}</c-></c->
</code></pre>
   <p>Example from <a data-link-type="biblio" href="#biblio-linuxinfoleak">[LinuxInfoleak]</a>. What can this leak? ASLR information, or
anything from another process. ASLR leak can enable Return Oriented Programming
(ROP) or make an arbitrary write effective (e.g., figure out where high-value
data structures are). Even padding has been shown to leak secrets.</p>
<pre class="highlight"><code class="highlight"><c- b><c- b>int</c-></c-> <c- nf><c- nf>queue_manage</c-></c-><c- p><c- p>()</c-></c-> <c- p><c- p>{</c-></c->
  <c- k><c- k>struct</c-></c-> <c- n><c- n>async_request</c-></c-> <c- o><c- o>*</c-></c-><c- n><c- n>backlog</c-></c-><c- p><c- p>;</c-></c->              <c- c1><c- c1>// uninitialized</c-></c->

  <c- k><c- k>if</c-></c-> <c- p><c- p>(</c-></c-><c- n><c- n>engine</c-></c-><c- o><c- o>-></c-></c-><c- n><c- n>state</c-></c-> <c- o><c- o>==</c-></c-> <c- n><c- n>IDLE</c-></c-><c- p><c- p>)</c-></c->                  <c- c1><c- c1>// usually true</c-></c->
    <c- n><c- n>backlog</c-></c-> <c- o><c- o>=</c-></c-> <c- n><c- n>get_backlog</c-></c-><c- p><c- p>(</c-></c-><c- o><c- o>&amp;</c-></c-><c- n><c- n>engine</c-></c-><c- o><c- o>-></c-></c-><c- n><c- n>queue</c-></c-><c- p><c- p>);</c-></c->

  <c- k><c- k>if</c-></c-> <c- p><c- p>(</c-></c-><c- n><c- n>backlog</c-></c-><c- p><c- p>)</c-></c->
    <c- n><c- n>backlog</c-></c-><c- o><c- o>-></c-></c-><c- n><c- n>complete</c-></c-><c- p><c- p>(</c-></c-><c- n><c- n>backlog</c-></c-><c- p><c- p>,</c-></c-> <c- o><c- o>-</c-></c-><c- n><c- n>EINPROGRESS</c-></c-><c- p><c- p>);</c-></c-> <c- c1><c- c1>// oops 🔥🔥🔥</c-></c->

  <c- k><c- k>return</c-></c-> <c- mi><c- mi>0</c-></c-><c- p><c- p>;</c-></c->
<c- p><c- p>}</c-></c->
</code></pre>
   <p>Example from <a data-link-type="biblio" href="#biblio-linuxuse">[LinuxUse]</a>. The attacker can control the value of <code class="highlight"><c- n>backlog</c-></code> by
making a previous function call, and ensuring the same stack slot gets reused.</p>
   <h3 class="heading settled" data-level="3.4" id="security-says"><span class="secno">3.4. </span><span class="content">Security Experts</span><a class="self-link" href="#security-says"></a></h3>
   <p>Security-minded folks think that initializing stack values is a good idea. For
example, the Microsoft Windows security team <a data-link-type="biblio" href="#biblio-winkernel">[WinKernel]</a> say:</p>
   <blockquote>
     Between 2017 and mid 2018, this feature would have
killed 49 MSRC cases that involved uninitialized struct data leaking across a
trust boundary. It would have also mitigated a number of bugs involving
uninitialized struct data being used directly. 
    <p>To date, we are seeing noise level performance regressions caused by this
change. We accomplished this by improving the compiler’s ability to kill
redundant stores. While everything is initialized at declaration, most of these
initializations can be proven redundant and eliminated.</p>
   </blockquote>
   <p>They use pure zero initialization, and claim to have taken the overheads down to
within noise. They provide more details in <a data-link-type="biblio" href="#biblio-cppconmsrc">[CppConMSRC]</a> and <a data-link-type="biblio" href="#biblio-initall">[InitAll]</a>. Don’t
just trust Microsoft’s Windows security team though, here’s one of the upstream
Linux Kernel security developer asking for this <a data-link-type="biblio" href="#biblio-clessdangerous">[CLessDangerous]</a>, and Linus
agreeing <a data-link-type="biblio" href="#biblio-linus">[Linus]</a>. <a data-link-type="biblio" href="#biblio-linuxexploits">[LinuxExploits]</a> is an overview of a real-world execution
control exploit using an uninitialized stack variable on Linux. It’s been
proposed for GCC <a data-link-type="biblio" href="#biblio-init-local-vars">[init-local-vars]</a> and LLVM <a data-link-type="biblio" href="#biblio-localinit">[LocalInit]</a> before.</p>
   <h3 class="heading settled" data-level="3.5" id="real-world"><span class="secno">3.5. </span><span class="content">In the Real World</span><a class="self-link" href="#real-world"></a></h3>
   <p>In Chrome we find 1100+ security bugs for “use of uninitialized value” <a data-link-type="biblio" href="#biblio-chromeuninit">[ChromeUninit]</a>.</p>
   <p>12% of all exploitable bugs in Android are of this kind according to <a data-link-type="biblio" href="#biblio-androidsec">[AndroidSec]</a>.</p>
   <p>Kostya Serebryany has a long list of issues caused by usage of
uninitialized stack variables <a data-link-type="biblio" href="#biblio-kcc">[KCC]</a>.</p>
   <h2 class="heading settled" data-level="4" id="alt"><span class="secno">4. </span><span class="content">Alternatives</span><a class="self-link" href="#alt"></a></h2>
   <p>When this is discussed, the discussion often goes to a few places.</p>
   <h3 class="heading settled" data-level="4.1" id="tools"><span class="secno">4.1. </span><span class="content">Tooling</span><a class="self-link" href="#tools"></a></h3>
   <p>First, people will suggest using tools such as memory sanitizer or valgrind. Yes
they should, but doing so:</p>
   <ul>
    <li data-md>
     <p>Requires compiling everything in the process with memory sanitizer.</p>
    <li data-md>
     <p>Can’t deploy in production.</p>
    <li data-md>
     <p>Only find that is executed in testing.</p>
    <li data-md>
     <p>3× slower and memory-hungry.</p>
   </ul>
   <h3 class="heading settled" data-level="4.2" id="try-harder"><span class="secno">4.2. </span><span class="content">Trying harder</span><a class="self-link" href="#try-harder"></a></h3>
   <p>The next suggestion is usually couldn’t you just test / fuzz / code-review
better or just write perfect code? However:</p>
   <ul>
    <li data-md>
     <p>We are (well, except the perfect code part).</p>
    <li data-md>
     <p>It’s not sufficient, as evidenced by the exploits.</p>
    <li data-md>
     <p>Attackers find what programmers don’t think of, and what fuzzers don’t hit.</p>
   </ul>
   <h3 class="heading settled" data-level="4.3" id="Werror"><span class="secno">4.3. </span><span class="content"><code class="highlight"><c- o>-</c-><c- n>Werror</c-><c- o>=</c-><c- n>uninitialized</c-></code></span><a class="self-link" href="#Werror"></a></h3>
   <p>The annoyed suggester then says "couldn’t you just use <code class="highlight"><c- o>-</c-><c- n>Werror</c-><c- o>=</c-><c- n>uninitialized</c-></code> and fix everything it complains about?" This is similar to the <a data-link-type="biblio" href="#biblio-coreguidelines">[CoreGuidelines]</a> recommendation. You are beginning to expect shortcoming, in
this case:</p>
   <ul>
    <li data-md>
     <p>Too much code to change.</p>
    <li data-md>
     <p>Current <code class="highlight"><c- o>-</c-><c- n>Wuninitialized</c-></code> is low quality, has false positives and false negatives. We could get better analysis if we had a compiler-frontend-based IR, but it still wouldn’t be noise-free.</p>
    <li data-md>
     <p>Similarly, static analysis isn’t smart enough.</p>
    <li data-md>
     <p>The value chosen to initialize doesn’t necessarily make sense, meaning that code might move from unsafe to merely incorrect.</p>
    <li data-md>
     <p>Code doesn’t express intent anymore, which leads readers to assume that the value is sensible when it might have simply been there to address the diagnostic.</p>
    <li data-md>
     <p>It prevents checkers (static analysis, sanitizers) from diagnosing code because it was given semantics which aren’t intended.</p>
   </ul>
   <h3 class="heading settled" data-level="4.4" id="definitive"><span class="secno">4.4. </span><span class="content">Definitive initialization</span><a class="self-link" href="#definitive"></a></h3>
   <p>Couldn’t you just use definitive initialization in the language? For example as
explained in <a data-link-type="biblio" href="#biblio-cppcondefinite">[CppConDefinite]</a> and <a data-link-type="biblio" href="#biblio-cppconcomplexity">[CppConComplexity]</a>. This one is
interesting. Languages such as C# and Swift allow uninitialized values, but only
if the compiler can prove that they’re not used uninitialized (that is, within
some set of rules), otherwise they must be initialized. It’s similar to
enforcing <code class="highlight"><c- o>-</c-><c- n>Wuninitialized</c-></code>, depending on what is standardized. We then have a
choice: standardize a simple analysis (such as "must be initialized within the
block or before it escapes") and risk needless initializations (with mitigations
explained in the prior references), or standardize a more complex analysis. We
would likely want to deploy a low-code-churn change, therefore a high-quality
analysis. This would require that the committee standardize the analysis, lest
compilers diverge. But a high-quality analysis tends to be complex, and change
as it improves, which is not sensible to standardize. This would leave us
standardizing a high-code-churn analysis with much more limited visibility.
Further with definitive initialization, it’s then unclear whether <code class="highlight"><c- b>int</c-> <c- n>derp</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c-></code> lends meaning to <code class="highlight"><c- mi>0</c-></code>, or whether it’s just there to shut that warning up.</p>
   <h3 class="heading settled" data-level="4.5" id="value-init"><span class="secno">4.5. </span><span class="content">Value initialization</span><a class="self-link" href="#value-init"></a></h3>
   <p>One alternative that was suggested instead of zero-initialization is to
value-initialize. This would invoke constructors in some cases and default
initialize in others, and therefore be a no-go as a significant behavior change
(with constructors being called) or a continuation of the uninitialized status
quo (when default initialization is performed).</p>
   <p>Something along these lines <a href="https://twitter.com/seanbax/status/1592741300964843520">is implemented in
the Circle compiler</a> under <code class="highlight"><c- cp>#pragma feature default_value_initialization</c-></code>.</p>
   <p>That said, some form of "trivial enough" initialization might be an acceptable
approach to increase correctness (not merely safety) for types for which zero
isn’t a valid value.</p>
   <h3 class="heading settled" data-level="4.6" id="fixit"><span class="secno">4.6. </span><span class="content">Fixing initialization</span><a class="self-link" href="#fixit"></a></h3>
   <p>Alisdair Meredith makes such a case. The sources of indeterminate values can be
eliminated as a group if we consider that the largest source of such values is
default initialization of scalar types, classes with a trivial default
constructor, aggregates containing either of both of the previous categories,
and data members of such type that are not initialized by a class’s constructor.</p>
   <p>If we were to eliminate default initialization entirely, and have only value
initialization, then this category of issue goes away entirely, and the
languages simpler and easier to learn. The behavior is not only well defined,
but intuitive. We lose corner cases that would lead to folks falling into vexing
parses, so explain that less often to students. The term “default constructed”
is no longer ambiguous, ending many pedantic conversations. Once value
initialization is the only semantic, the term “default Initialization” can be
repurposed to mean exactly that.</p>
   <p>Once values are always determinate (even if unspecified) then a whole category of
reference abuse, notably through function calls, goes away.  We do not lose the
undefined behavior of a forced bad cast, or an expired object though.</p>
   <p>This approach could simplify the language as a whole. Indeed, initialization in
C++ is already quite complex. However, it would initialize heap values which, as
discussed in this paper, would have unacceptable performance impact.</p>
   <h3 class="heading settled" data-level="4.7" id="do-nothing"><span class="secno">4.7. </span><span class="content">Do nothing</span><a class="self-link" href="#do-nothing"></a></h3>
   <p>We could instead keep the out-of-band option that is already implemented in all
major compilers. That out-of-band option is opt-in and keeps the status quo
where "C++ is unsafe by default". Further, many compiler implementors are
dissatisfied by this option because they believe it’s effectively a language
fork that users of the out-of-band option will come to rely on (this strategy is
mitigated in MSVC by using a non-zero pattern in debug builds according to <a data-link-type="biblio" href="#biblio-initall">[InitAll]</a>). These developers would rather see the language standardize the
option officially (i.e., standardize existing practice).</p>
   <h3 class="heading settled" data-level="4.8" id="ffff"><span class="secno">4.8. </span><span class="content">Other values</span><a class="self-link" href="#ffff"></a></h3>
   <p>Rather than zero-initializing, we could use another value. For example, the
author implemented a mode where the fundamental types dictate the value used:</p>
   <ul>
    <li data-md>
     <p>Integral → repeated <code class="highlight"><c- mh>0xAA</c-></code></p>
    <li data-md>
     <p>Pointers → repeated <code class="highlight"><c- mh>0xAA</c-></code></p>
    <li data-md>
     <p>Floating-point → repeated <code class="highlight"><c- mh>0xFF</c-></code></p>
   </ul>
   <p>This is advantageous in 64-bit platforms because all pointer uses will trap with
a recognizable value, though most modern platforms will also trap for large
offsets from the null pointer. Floating-point values are NaNs with payload,
which propagate on floating-point operations and are therefore easy to
root-cause. It is problematic for some integer values that represent sizes in a
bounds check, because such a number is effectively larger that any bounds and
would potentially permit out-of-bounds accesses that a zero initialization would
not.</p>
   <p>Unfortunately, this scheme optimizes much more poorly and end up being a roughly
1.5% size and performance regression on some workloads according to <a data-link-type="biblio" href="#biblio-googlenumbers">[GoogleNumbers]</a> and others.</p>
   <p>Using repeated bytes for initialization is critical to effective code generation
because instruction sets can materialize repeated byte patterns much more
efficiently than any larger value. Any approach other than the above is bound to
have a worst performance impact. That is why choosing implementation-defined
values or runtime random values isn’t a useful approach.</p>
   <p>There have been discussions of other more complex schemes (such as using
pseudo-random values), all of which perform even worst.</p>
   <h3 class="heading settled" data-level="4.9" id="impl-def"><span class="secno">4.9. </span><span class="content">Implementation defined</span><a class="self-link" href="#impl-def"></a></h3>
   <p>Another alternative is to guarantee that accessing uninitialized values is
implementation-defined behavior, where implementations <em>must</em> choose to either,
on a per-value basis:</p>
   <ul>
    <li data-md>
     <p>zero-initialize; or</p>
    <li data-md>
     <p>trap (we can argue separately as to whether "trap" is immediate
 termination, Itanium <a data-link-type="biblio" href="#biblio-nat">[NaT]</a>, or <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>terminate</c-></code>, or <a href="https://twitter.com/jfbastien/status/1245362601367760896">ring a bell</a>,
 or something else).</p>
   </ul>
   <p>Implementations would then do their best to trap on uninitialized value access,
but when they can’t prove that an access is uninitialized through however
complex optimization scheme, they would revert to zero-initialization. This is
an interesting approach which Richard Smith has prototyped in <a data-link-type="biblio" href="#biblio-trap">[Trap]</a>. However, the author’s and others' experience is that such a change is
rejected by teams because it cannot be deployed to codebases that seem to work
just fine. The Committee might decide to go with this approach, and see whether
the default in various implementations is "always zero" or "sometimes trap".</p>
   <p>The committee might otherwise choose to leave the object representation as
implementation-defined (hence definite), but retrict the valid implementation
strategies so that the value representation remains indeterminate. This would
disallow trapping in a conforming implementation, but would still prevent users
from relying on a particular value. An implementation could nonetheless elect to
trap (in a non-conforming mode), which is similar to what UBSan does on some
behaviors (for example, some signed overflows can trap, which is
non-conforming).</p>
   <h3 class="heading settled" data-level="4.10" id="hybrid"><span class="secno">4.10. </span><span class="content">Hybrid approach</span><a class="self-link" href="#hybrid"></a></h3>
   <p>We could also standardize a hybrid approach that mixes some of the above,
creating implementation-defined alternatives which are effectively different
build modes that the standard allows. This is what <a data-link-type="biblio" href="#biblio-carboninit">[CarbonInit]</a> does.</p>
   <h3 class="heading settled" data-level="4.11" id="overwrite"><span class="secno">4.11. </span><span class="content">Overwrite</span><a class="self-link" href="#overwrite"></a></h3>
   <p>A different proposal can be found in <a data-link-type="biblio" href="#biblio-d2488r0">[D2488R0]</a> which proposes attribute <code class="highlight"><c- p>[[</c-><c- n>for_overwrite</c-><c- p>]]</c-></code>. This approach distinguishes itself by having the developer
annotate values which are expected to never be read. It does not address the
problem at hand in a comprehensive manner.</p>
   <h3 class="heading settled" data-level="4.12" id="rust-ub"><span class="secno">4.12. </span><span class="content">Rust <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>uninitialized</c-></code></span><a class="self-link" href="#rust-ub"></a></h3>
   <p>The author has received feedback requesting an approach similar to Rust’s <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>uninitialized</c-></code>. This is a bad idea <a href="https://doc.rust-lang.org/std/mem/fn.uninitialized.html">as explained by Rust’s documentation of
the deprecated feature</a>:</p>
   <blockquote>
     The reason for deprecation is that the function basically cannot be used correctly: it has the same effect as MaybeUninit::uninit().assume_init(). As the assume_init documentation explains, the Rust compiler assumes that values are properly initialized. 
    <p>Truly uninitialized memory like what gets returned here is special in that the compiler knows that it does not have a fixed value. This makes it undefined behavior to have uninitialized data in a variable even if that variable has an integer type.</p>
    <p>Therefore, it is immediate undefined behavior to call this function on nearly all types, including integer types and arrays of integer types, and even if the result is unused.</p>
   </blockquote>
   <h3 class="heading settled" data-level="4.13" id="wobble"><span class="secno">4.13. </span><span class="content">Wobbly bits</span><a class="self-link" href="#wobble"></a></h3>
   <p>The WG14 C Standards Committee has had extensive discussions about "wobbly
values" and "wobbly bits", specifically around <a data-link-type="biblio" href="#biblio-dr451">[DR451]</a> and <a data-link-type="biblio" href="#biblio-n1793">[N1793]</a>,
summarized in <a data-link-type="biblio" href="#biblio-seacord">[Seacord]</a>.</p>
   <p>The C Standards Committee has not reached a conclusion for C23, and wobbly bits
continue to wobble indeterminately.</p>
   <h3 class="heading settled" data-level="4.14" id="🧙"><span class="secno">4.14. </span><span class="content">New Word of Power</span><a class="self-link" href="#🧙"></a></h3>
   <p>The C++ Standards Committee isn’t stuck with "undefined behavior",
"implementation defined behavior", "unspecified behavior", "ill-formed", and
"ill-formed, no diagnostic required". Indeed, the Standards Committee made up
these words and their meaning, and can make up new words with new and exciting
meaning.</p>
   <h4 class="heading settled" data-level="4.14.1" id="to-err-is-human"><span class="secno">4.14.1. </span><span class="content">Erroneous Behavior</span><a class="self-link" href="#to-err-is-human"></a></h4>
   <p>An interesting proposal from the most wonderful Thomas Köppe is to will into
being the concept of "erroneous behavior": well-defined behavior which permits
the implementation to emit a diagnostic.</p>
   <p>Under "erroneous behavior", diagnostics are not tied to the erroneous
evaluation, but can happen at any later point, or never.</p>
   <p>"Erroneous behavior" acknowledges that real programs
contain errors. Erroneous behavior is always a programming error, but it is not
always diagnosable by every desirable implementation. An erroneous result is
well-defined, but never intentional.</p>
   <p>A program execution that does not have erroneous behavior is called
"error-free".</p>
   <p>An implementation will surely offer a setting that asserts that a program is
error-free, which turns any erroneous into undefined behavior and restores the
status quo ante. Similarly, a (different) implementation may be able to diagnose
all erroneous behavior, but at a cost.</p>
   <p>A design question arises: we might want the rule "if a diagnostic is emitted,
the behavior is undefined", allowing arbitrary things to happen if an
implementation chooses to diagnose an erroneous behavior (e.g., terminate,
log-and-continue, etc.). Although it would be nice to bound that somewhat to,
say, "either not return, or continue with the specified effects and values".</p>
   <p>With this new tool available, we can respecify a previously undefined behavior
to a well-defined, erroneous behavior. For example:</p>
   <p>A default-initialized automatic variable has an implementation-defined object
representation. Performing <code class="highlight"><c- n>gl2pr</c-></code> on that variable erroneously results in the
value implied by that object representation. Note: the compiler must produce
that specific, implementation-defined value, because that’s the value all further
uses see until a diagnostic is raised (if ever). Because the diagnostic may be
raised in a different translation unit at a later point, up to which the
behavior remains well-defined, the compiler can’t eagerly assume that the value
won’t be used.</p>
   <p>This approach differs from attempts at defining "bounded undefined behavior", by
approaching the problem space from the other direction. Instead of modifying and
restricting the consequences of undefined behavior, we instead relax the
requirements on well-defined behavior, and therefore make well-defined behavior
an acceptable choice for certain (otherwise) unacceptable coding patterns. This
avoids touching undefined behavior altogether, and instead allows us to
selectively strengthen the specification of certain operations where we deem the
risk from erroneous use to be high enough to warrant the performance cost. I
think it is valuable to call out in the Standard that real programs
contain errors, because it is hard otherwise to discuss what we are trying to
achieve.</p>
   <h4 class="heading settled" data-level="4.14.2" id="words"><span class="secno">4.14.2. </span><span class="content">Other Words</span><a class="self-link" href="#words"></a></h4>
   <p>The author is certain that we could invent many other fun words, with amazing
meaning. As with all alternatives, the author would appreciate practicality when
discussing what could be done. Does the new word actually solve the security and
safety issue at hand, is it implementable, and is it acceptable to deploy? Or
are we just shooting the shit? The author likes fun, but let’s please have the
right fun at the right place.</p>
   <h2 class="heading settled" data-level="5" id="perf"><span class="secno">5. </span><span class="content">Performance</span><a class="self-link" href="#perf"></a></h2>
   <p>Previous publications <a data-link-type="biblio" href="#biblio-zeroing">[Zeroing]</a> have cited 2.7 to 4.5% averages. This was true
because, in the author’s experience implementing this in LLVM <a data-link-type="biblio" href="#biblio-llvmjfb">[LLVMJFB]</a>, the
compiler simply didn’t perform sufficient optimizations. Deploying this change
required a variety of optimizations to remove needless work and reduce code
size. These optimizations were generally useful for other code, not just
automatic variable initialization.</p>
   <p>As stated in the introduction, the performance impact is now negligible (less
that 0.5% regression) to slightly positive (that is, some code gets <em>faster</em> by
up to 1%). The code size impact is negligible (smaller than 0.5%).</p>
   <p>Why do we sometimes observe a performance progression with zero-initialization?
There are a few potential reasons:</p>
   <ul>
    <li data-md>
     <p>Zeroing a register or stack value can break dependencies, allowing more
Instructions Per Cycles (IPC) in an out-of-order CPU by unblocking scheduling
of instructions that were waiting on what seemed like a long critical path of
instructions but were in fact only false-sharing registers. The register can
be renamed to the hardware-internal zero register, and instructions scheduled.</p>
    <li data-md>
     <p>Zeroing of entire cache entries is magical, though for the stack this is
rarely the case. There’s questions of temporality, special instructions, and
special logic to support zeroed cachelines.</p>
   </ul>
   <p>Here are a few of the optimizations which have helped reduce overheads in LLVM:</p>
   <ul>
    <li data-md>
     <p>CodeGen: use non-zero <code class="highlight"><c- n>memset</c-></code> for automatic variables <a href="https://llvm.org/D49771">D49771</a></p>
    <li data-md>
     <p>Merge clang’s <code class="highlight"><c- n>isRepeatedBytePattern</c-></code> with LLVM’s <code class="highlight"><c- n>isBytewiseValue</c-></code> <a href="https://llvm.org/D51751">D51751</a></p>
    <li data-md>
     <p>SelectionDAG: Reuse bigger constants in <code class="highlight"><c- n>memset</c-></code> <a href="https://llvm.org/D53181">D53181</a></p>
    <li data-md>
     <p>ARM64: improve non-zero <code class="highlight"><c- n>memset</c-></code> isel by ~2x <a href="https://llvm.org/D51706">D51706</a></p>
    <li data-md>
     <p>Double sign-extend stores not merged going to stack <a href="https://llvm.org/D54846">D54846</a> and <a href="https://llvm.org/D54847">D54847</a></p>
    <li data-md>
     <p>LoopUnroll: support loops w/ exiting headers &amp; uncond latches <a href="https://llvm.org/D61962">D61962</a></p>
    <li data-md>
     <p>ConstantMerge: merge common initial sequences <a href="https://llvm.org/D50593">D50593</a></p>
    <li data-md>
     <p>IPO should track pointer values which are written to, enabling DSO <a href="https://lists.llvm.org/pipermail/cfe-dev/2019-January/060919.html">DSO</a></p>
    <li data-md>
     <p>Missed dead store across basic blocks <a href="https://llvm.org/pr40527">pr40527</a></p>
   </ul>
   <p>This doesn’t cover all relevant optimizations. Some optimizations will be
architecture-specific, meaning that deploying this change to new architectures
will require some optimization work to reduce cost.</p>
   <p>New codebases using automatic variable initialization might trigger
missed-optimizations in compilers and experience a performance or size
regression. The wide deployment of the opt-in compiler flag means that this is
unlikely, but were this to happen then a bug should be filed against the
compiler to fix the missed optimization.</p>
   <p>For example, here is Android’s experience on performance costs <a data-link-type="biblio" href="#biblio-androidcosts">[AndroidCosts]</a>.</p>
   <p>Some of the performance costs are hidden by modern CPUs being heavily
superscalar. Embedded CPUs are often in-order, code running on them might
therefore have a performance regression that is roughly proportional to code
size increases. Here too, compiler optimizations can significantly reduce these
costs.</p>
   <h2 class="heading settled" data-level="6" id="caveats"><span class="secno">6. </span><span class="content">Caveats</span><a class="self-link" href="#caveats"></a></h2>
   <p>There are a few caveats to this proposal.</p>
   <p>Making all automatic variables explicitly zero means that developers will come
to rely on it. The current status-quo forces developers to express intent, and
new code might decide not to do so and simply use the zero that they know to be
there. This would then make it impossible to distinguish "purposeful use of the
uninitialized zero" from "accidental use of the uninitialized zero". Tools such
as static analysis, memory sanitizers, and valgrind would therefore be unable to
diagnose correctness issues (but we would have removed the security issues). It
should still be best practice to only assign a value to a variable when this
value is meaningful, and only use an "uninitialized" value when meaning has been
given to it.</p>
   <p>Some types might not have a valid zero value, for example an enum might not
assign meaning to zero. Initializing this type to zero is then safe, but not
correct. However, C++ has constructors to deal with this type of issue.</p>
   <p>For some types, the zero value might be the "dangerous" one, for example a null
pointer might be a special sentinel value saying "has all privileges" in a
kernel. A concrete example is on Linux where <code class="highlight"><c- n>task</c-><c- o>-></c-><c- n>uid</c-></code> of zero means <code class="highlight"><c- n>root</c-></code>,
uninitialized reads of zero have been the source of CVEs on Linux before.</p>
   <p>The core of the above objections is that this change isn’t always safe (it’s
simply safer than uninitialized), and isn’t necessarily correct in all
circumstances (it’s simply correct more often than uninitialized). Sensible
people reach different conclusions because of these facts.</p>
   <p>This proposal will now mean that objects with dynamic storage duration are now
uniquely different from all other storage duration objects (automatic, static,
and thread local), in that they alone are uninitialized. We could explore
guaranteeing initialization of these objects, but this is a much newer area of
research and deployment as shown in <a data-link-type="biblio" href="#biblio-xnuheap">[XNUHeap]</a>. The strategy for automatically
initializing objects of dynamic storage durations depend on a variety of
factors, there’s no agreed-upon one right solution for all codebases. Each
implementation approach has tradeoffs that warrant more study.</p>
   <p>Some people think that reading uninitialized stack variables is a good source of
randomness to seed a random number generator, but these people are wrong <a data-link-type="biblio" href="#biblio-randomness">[Randomness]</a>.</p>
   <p>As an implementation concern for LLVM (and maybe others), not all variables of
automatic storage duration are easy to properly zero-initialize. Variables
declared in unreachable code, and used later, aren’t currently initialized. This
includes <code class="highlight"><c- k>goto</c-></code>, Duff’s device, other objectionable uses of <code class="highlight"><c- k>switch</c-></code>. Such
things should rather be a hard-error in any serious codebase.</p>
   <p><code class="highlight"><c- k>volatile</c-></code> stack variables are weird. That’s pre-existing, it’s really the
language’s fault and this proposal keeps it weird. In LLVM, the author opted to
initialize all <code class="highlight"><c- k>volatile</c-></code> stack variables to zero. This is technically
acceptable because they don’t have any special hardware or external meaning,
they’re only used to block the optimizer, or in rare cases preserve values
across <code class="highlight"><c- n>setjmp</c-></code> / <code class="highlight"><c- n>longjmp</c-></code> or signals. The double initialization is technically
incorrect because the compiler shouldn’t be performing extra accesses to <code class="highlight"><c- k>volatile</c-></code> variables, but one could argue that the compiler is zero-initializing
the storage right before the <code class="highlight"><c- k>volatile</c-></code> is constructed. This would be a
pointless discussion which the author is happy to have if the counterparty is
buying.</p>
   <h2 class="heading settled" data-level="7" id="word"><span class="secno">7. </span><span class="content">Wording</span><a class="self-link" href="#word"></a></h2>
   <p>Wording for this proposal will be provided once an approach is agreed upon.</p>
   <p>The author expects that the solution that is agreed upon maintains the property
that:</p>
   <ul>
    <li data-md>
     <p>Taking the address, passing this address, and manipulating the address of
 data not explicitly initialized remains valid.</p>
    <li data-md>
     <p><code class="highlight"><c- n>memcpy</c-></code> of data not explicitly initialized (including padding) remains
 valid, but reading from the data or the <code class="highlight"><c- n>memcpy</c-></code>d data is currently
 invalid.</p>
   </ul>
   <h2 class="heading settled" data-level="8" id="feedback"><span class="secno">8. </span><span class="content">Feedback</span><a class="self-link" href="#feedback"></a></h2>
   <p>The first version of this proposal, <a data-link-type="biblio" href="#biblio-p2723r0">[P2723r0]</a>, has received substantial
feedback. This feedback is difficult to summarize, but here are a few
(initialized) pointers:</p>
   <ul>
    <li data-md>
     <p>The author’s <a href="https://twitter.com/jfbastien/status/1592578174763745280">original Twitter link</a> generated 100 direct replied (many more sub-replies), received 1.96K likes, 350 retweets, and 304K impressions. Hard to summarize, but most of the interactions were about not having read the paper. Some great feedback came from Twitter, and has been integrated into the paper. The feedback about not having read the paper has been integrated as well, in that the paper hasn’t read itself.</p>
    <li data-md>
     <p>The author’s <a href="https://mastodon.social/@jfbastien/109347583584387285">original Mastodon link</a> generated 40 direct replied (many more sub-replies), received 237 likes, and 128 boosts. The feedback was similar to Twitter, but Mastodon calls it "toots" instead of "tweets" so it’s arguably higher quality.</p>
    <li data-md>
     <p><a href="https://lobste.rs/s/lvb8in/p2723r0_zero_initialize_objects">lobste.rs</a> had a small discussion, 9 comments in total, the most valuable of which supported the author’s dad jokes. Close second stated "HardenedBSD recently switched to auto init to zero by default for the entire userland OS/ecosystem, including 33,000+ packages. Very quite literally zero noticeable performance hit.".</p>
    <li data-md>
     <p><a href="https://www.reddit.com/r/cpp/comments/yzhh73/p2723r0_zeroinitialize_objects_of_automatic/">r/cpp</a> was a thing, with 205 comments. The nuance of these deeps discussions cannot be captured in this paper.</p>
    <li data-md>
     <p>Slashdot did not discuss, but the author hears that Slashdot is still in existence.</p>
    <li data-md>
     <p>The <a href="https://lists.isocpp.org/ext/2022/11/20055.php">C++ Committee’s internal EWG list received 369 emails responding to this paper</a>. Some great comments were hidden in these 369 replies, and the author hopes to have captured them in the first revision of the paper.</p>
    <li data-md>
     <p>A variety of security professionals have reached out privately to the author, all of their feedback was of the form "ship it".</p>
    <li data-md>
     <p>Limited feedback from finance / high-frequency trading firms who reached out privately to the author. Their feedback was surprisingly positive "as long as we can opt-out", with a concern about having tooling to help identify potential performance issues.</p>
    <li data-md>
     <p>Graydon Hoare (creator of Rust, and all-around wonderful human) posted a link to the first version of this paper and <a href="https://types.pl/@graydon/109527700421713074">followed up with "(Speaking of utterly heroic JF Bastien moves)"</a>. The author now questions whether this paper is a conspiracy by the Rust Evangelism Strike Force. 🦀</p>
   </ul>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

  var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
  var autoToggle   = function(e){ toggleSidebar(e.matches) };
  if(sidebarMedia.addListener) {
    sidebarMedia.addListener(autoToggle);
  }

  function toggleSidebar(on) {
    if (on == undefined) {
      on = !document.body.classList.contains('toc-sidebar');
    }

    /* Don’t scroll to compensate for the ToC if we’re above it already. */
    var headY = 0;
    var head = document.querySelector('.head');
    if (head) {
      // terrible approx of "top of ToC"
      headY += head.offsetTop + head.offsetHeight;
    }
    var skipScroll = window.scrollY < headY;

    var toggle = document.getElementById('toc-toggle');
    var tocNav = document.getElementById('toc');
    if (on) {
      var tocHeight = tocNav.offsetHeight;
      document.body.classList.add('toc-sidebar');
      document.body.classList.remove('toc-inline');
      toggle.innerHTML = collapseSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, 0 - tocHeight);
      }
      tocNav.focus();
      sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
    }
    else {
      document.body.classList.add('toc-inline');
      document.body.classList.remove('toc-sidebar');
      toggle.innerHTML = expandSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, tocNav.offsetHeight);
      }
      if (toggle.matches(':hover')) {
        /* Unfocus button when not using keyboard navigation,
           because I don’t know where else to send the focus. */
        toggle.blur();
      }
    }
  }

  function createSidebarToggle() {
    /* Create the sidebar toggle in JS; it shouldn’t exist when JS is off. */
    var toggle = document.createElement('a');
      /* This should probably be a button, but appearance isn’t standards-track.*/
    toggle.id = 'toc-toggle';
    toggle.class = 'toc-toggle';
    toggle.href = '#toc';
    toggle.innerHTML = collapseSidebarText;

    sidebarMedia.addListener(autoToggle);
    var toggler = function(e) {
      e.preventDefault();
      sidebarMedia.removeListener(autoToggle); // persist explicit off states
      toggleSidebar();
      return false;
    }
    toggle.addEventListener('click', toggler, false);


    /* Get <nav id=toc-nav>, or make it if we don’t have one. */
    var tocNav = document.getElementById('toc-nav');
    if (!tocNav) {
      tocNav = document.createElement('p');
      tocNav.id = 'toc-nav';
      /* Prepend for better keyboard navigation */
      document.body.insertBefore(tocNav, document.body.firstChild);
    }
    /* While we’re at it, make sure we have a Jump to Toc link. */
    var tocJump = document.getElementById('toc-jump');
    if (!tocJump) {
      tocJump = document.createElement('a');
      tocJump.id = 'toc-jump';
      tocJump.href = '#toc';
      tocJump.innerHTML = tocJumpText;
      tocNav.appendChild(tocJump);
    }

    tocNav.appendChild(toggle);
  }

  var toc = document.getElementById('toc');
  if (toc) {
    createSidebarToggle();
    toggleSidebar(sidebarMedia.matches);

    /* If the sidebar has been manually opened and is currently overlaying the text
       (window too small for the MQ to add the margin to body),
       then auto-close the sidebar once you click on something in there. */
    toc.addEventListener('click', function(e) {
      if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
        toggleSidebar(false);
      }
    }, false);
  }
  else {
    console.warn("Can’t find Table of Contents. Please use <nav id='toc'> around the ToC.");
  }

  /* Wrap tables in case they overflow */
  var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
  var numTables = tables.length;
  for (var i = 0; i < numTables; i++) {
    var table = tables[i];
    var wrapper = document.createElement('div');
    wrapper.className = 'overlarge';
    table.parentNode.insertBefore(wrapper, table);
    wrapper.appendChild(table);
  }

})();
</script>
  <h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
  <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
  <dl>
   <dt id="biblio-androidcosts">[AndroidCosts]
   <dd>Alexander Potapenko. <a href="https://clangbuiltlinux.github.io/CBL-meetup-2020-slides/glider/Fighting_uninitialized_memory_%40_CBL_Meetup_2020.pdf">Fighting Uninitialized Memory in the Kernel</a>. 2020. URL: <a href="https://clangbuiltlinux.github.io/CBL-meetup-2020-slides/glider/Fighting_uninitialized_memory_%40_CBL_Meetup_2020.pdf">https://clangbuiltlinux.github.io/CBL-meetup-2020-slides/glider/Fighting_uninitialized_memory_%40_CBL_Meetup_2020.pdf</a>
   <dt id="biblio-androidsec">[AndroidSec]
   <dd>Nick Kralevich. <a href="https://www.blackhat.com/docs/us-16/materials/us-16-Kralevich-The-Art-Of-Defense-How-Vulnerabilities-Help-Shape-Security-Features-And-Mitigations-In-Android.pdf">How vulnerabilities help shape security features and mitigations in Android</a>. 2016-08-04. URL: <a href="https://www.blackhat.com/docs/us-16/materials/us-16-Kralevich-The-Art-Of-Defense-How-Vulnerabilities-Help-Shape-Security-Features-And-Mitigations-In-Android.pdf">https://www.blackhat.com/docs/us-16/materials/us-16-Kralevich-The-Art-Of-Defense-How-Vulnerabilities-Help-Shape-Security-Features-And-Mitigations-In-Android.pdf</a>
   <dt id="biblio-autoinitsummary">[AutoInitSummary]
   <dd>Florian Hahn. <a href="https://lists.llvm.org/pipermail/llvm-dev/2020-November/146393.html">[llvm-dev] RFC: Combining Annotation Metadata and Remarks</a>. 2020-11-04. URL: <a href="https://lists.llvm.org/pipermail/llvm-dev/2020-November/146393.html">https://lists.llvm.org/pipermail/llvm-dev/2020-November/146393.html</a>
   <dt id="biblio-carboninit">[CarbonInit]
   <dd>Chandler Carruth. <a href="https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0257.md">Carbon: Initialization of memory and variables</a>. 2021-06-22. URL: <a href="https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0257.md">https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0257.md</a>
   <dt id="biblio-chromeuninit">[ChromeUninit]
   <dd>multiple. <a href="https://bugs.chromium.org/p/chromium/issues/list?can=1&amp;q=Stability%3DMemory-MemorySanitizer+-status%3ADuplicate+-status%3AWontFix+Use-of-uninitialized-value">Chromium code search for Use-of-uninitialized-value</a>. multiple. URL: <a href="https://bugs.chromium.org/p/chromium/issues/list?can=1&amp;q=Stability%3DMemory-MemorySanitizer+-status%3ADuplicate+-status%3AWontFix+Use-of-uninitialized-value">https://bugs.chromium.org/p/chromium/issues/list?can=1&amp;q=Stability%3DMemory-MemorySanitizer+-status%3ADuplicate+-status%3AWontFix+Use-of-uninitialized-value</a>
   <dt id="biblio-clessdangerous">[CLessDangerous]
   <dd>Kees Cook. <a href="https://outflux.net/slides/2018/lss/danger.pdf">Making C Less Dangerous</a>. 2018-08-28. URL: <a href="https://outflux.net/slides/2018/lss/danger.pdf">https://outflux.net/slides/2018/lss/danger.pdf</a>
   <dt id="biblio-coreguidelines">[CoreGuidelines]
   <dd>Herb Sutter; Bjarne Stroustrup. <a href="https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-always">C++ Core Guidelines: ES.20: Always initialize an object</a>. unknown. URL: <a href="https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-always">https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-always</a>
   <dt id="biblio-cppconcomplexity">[CppConComplexity]
   <dd>Herb Sutter. <a href="https://www.youtube.com/watch?v=6lurOCdaj0Y&amp;t=971s">Empirically Measuring, &amp; Reducing, C++’s Accidental Complexity</a>. 2020-10-11. URL: <a href="https://www.youtube.com/watch?v=6lurOCdaj0Y&amp;t=971s">https://www.youtube.com/watch?v=6lurOCdaj0Y&amp;t=971s</a>
   <dt id="biblio-cppcondefinite">[CppConDefinite]
   <dd>Herb Sutter. <a href="https://www.youtube.com/clip/UgkxpWxXNaoWvGqhlpSdWRQs0M3ayQcEhDoh">Can C++ be 10x Simpler &amp; Safer?</a>. 2022-11-13. URL: <a href="https://www.youtube.com/clip/UgkxpWxXNaoWvGqhlpSdWRQs0M3ayQcEhDoh">https://www.youtube.com/clip/UgkxpWxXNaoWvGqhlpSdWRQs0M3ayQcEhDoh</a>
   <dt id="biblio-cppconmsrc">[CppConMSRC]
   <dd>Joseph Bialek; Shayne Hiet-Block. <a href="https://www.youtube.com/watch?v=rQWjF8NvqAU">Killing Uninitialized Memory: Protecting the OS Without Destroying Performance</a>. 2019-10-13. URL: <a href="https://www.youtube.com/watch?v=rQWjF8NvqAU">https://www.youtube.com/watch?v=rQWjF8NvqAU</a>
   <dt id="biblio-cwe-457">[CWE-457]
   <dd>MITRE. <a href="https://cwe.mitre.org/data/definitions/457.html">CWE-457: Use of Uninitialized Variable</a>. 2006-07-19. URL: <a href="https://cwe.mitre.org/data/definitions/457.html">https://cwe.mitre.org/data/definitions/457.html</a>
   <dt id="biblio-d2488r0">[D2488R0]
   <dd>Andrzej Krzemieński. <a href="https://isocpp.org/files/papers/D2488R0.html">Attribute [[for_overwrite]]</a>. 2021-11-11. URL: <a href="https://isocpp.org/files/papers/D2488R0.html">https://isocpp.org/files/papers/D2488R0.html</a>
   <dt id="biblio-dr451">[DR451]
   <dd>Freek Wiedijk; Robbert Krebbers. <a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_451.htm">Instability of uninitialized automatic variables</a>. 2013-08-30. URL: <a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_451.htm">https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_451.htm</a>
   <dt id="biblio-gccreview">[GCCReview]
   <dd>Qing Zhao. <a href="https://gcc.gnu.org/pipermail/gcc-patches/2021-February/565514.html">[RFC][patch for gcc12][version 1] add -ftrivial-auto-var-init and variable attribute "uninitialized" to gcc</a>. 2021-02-18. URL: <a href="https://gcc.gnu.org/pipermail/gcc-patches/2021-February/565514.html">https://gcc.gnu.org/pipermail/gcc-patches/2021-February/565514.html</a>
   <dt id="biblio-googlenumbers">[GoogleNumbers]
   <dd>Kostya Serebryany. <a href="https://lists.llvm.org/pipermail/cfe-dev/2019-January/060878.html">[cfe-dev] [RFC] automatic variable initialization</a>. 2019-01-16. URL: <a href="https://lists.llvm.org/pipermail/cfe-dev/2019-January/060878.html">https://lists.llvm.org/pipermail/cfe-dev/2019-January/060878.html</a>
   <dt id="biblio-init-local-vars">[INIT-LOCAL-VARS]
   <dd>Florian Weimer. <a href="https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00615.html">-finit-local-vars option</a>. 2014-06-06. URL: <a href="https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00615.html">https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00615.html</a>
   <dt id="biblio-initall">[InitAll]
   <dd>Joseph Bialek. <a href="https://msrc-blog.microsoft.com/2020/05/13/solving-uninitialized-stack-memory-on-windows/">Solving Uninitialized Stack Memory on Windows</a>. 2020-05-13. URL: <a href="https://msrc-blog.microsoft.com/2020/05/13/solving-uninitialized-stack-memory-on-windows/">https://msrc-blog.microsoft.com/2020/05/13/solving-uninitialized-stack-memory-on-windows/</a>
   <dt id="biblio-kcc">[KCC]
   <dd>Kostya Serebryany. <a href="https://lists.llvm.org/pipermail/cfe-dev/2018-November/060177.html">[cfe-dev] [RFC] automatic variable initialization</a>. 2018-11-15. URL: <a href="https://lists.llvm.org/pipermail/cfe-dev/2018-November/060177.html">https://lists.llvm.org/pipermail/cfe-dev/2018-November/060177.html</a>
   <dt id="biblio-linus">[Linus]
   <dd>Linus Torvalds. <a href="https://lore.kernel.org/lkml/CAHk-=wgTM+cN7zyUZacGQDv3DuuoA4LORNPWgb1Y_Z1p4iedNQ@mail.gmail.com/">Re: [GIT PULL] meminit fix for v5.3-rc2</a>. 2019-06-30. URL: <a href="https://lore.kernel.org/lkml/CAHk-=wgTM+cN7zyUZacGQDv3DuuoA4LORNPWgb1Y_Z1p4iedNQ@mail.gmail.com/">https://lore.kernel.org/lkml/CAHk-=wgTM+cN7zyUZacGQDv3DuuoA4LORNPWgb1Y_Z1p4iedNQ@mail.gmail.com/</a>
   <dt id="biblio-linuxexploits">[LinuxExploits]
   <dd>Kees Cook. <a href="https://outflux.net/slides/2011/defcon/kernel-exploitation.pdf">Kernel Exploitation via Uninitialized Stack</a>. 2019-08. URL: <a href="https://outflux.net/slides/2011/defcon/kernel-exploitation.pdf">https://outflux.net/slides/2011/defcon/kernel-exploitation.pdf</a>
   <dt id="biblio-linuxinfoleak">[LinuxInfoleak]
   <dd>Mathias Krause. <a href="https://seclists.org/oss-sec/2013/q1/693">Linux kernel: net - three info leaks in rtnl</a>. 2013-03-19. URL: <a href="https://seclists.org/oss-sec/2013/q1/693">https://seclists.org/oss-sec/2013/q1/693</a>
   <dt id="biblio-linuxuse">[LinuxUse]
   <dd>Kangjie Lu; et al. <a href="https://www-users.cs.umn.edu/~kjlu/papers/tss.pdf">Unleashing Use-Before-Initialization Vulnerabilities in the Linux Kernel Using Targeted Stack Spraying</a>. 2017-03-01. URL: <a href="https://www-users.cs.umn.edu/~kjlu/papers/tss.pdf">https://www-users.cs.umn.edu/~kjlu/papers/tss.pdf</a>
   <dt id="biblio-llvmjfb">[LLVMJFB]
   <dd>JF Bastien. <a href="https://www.youtube.com/watch?v=I-XUHPimq3o">Mitigating Undefined Behavior</a>. 2019-12-12. URL: <a href="https://www.youtube.com/watch?v=I-XUHPimq3o">https://www.youtube.com/watch?v=I-XUHPimq3o</a>
   <dt id="biblio-llvmreview">[LLVMReview]
   <dd>JF Bastien. <a href="https://reviews.llvm.org/D54604">Automatic variable initialization</a>. 2018-11-15. URL: <a href="https://reviews.llvm.org/D54604">https://reviews.llvm.org/D54604</a>
   <dt id="biblio-localinit">[LocalInit]
   <dd>thestinger. <a href="https://github.com/AndroidHardeningArchive/platform_external_clang/commit/776a0955ef6686d23a82d2e6a3cbd4a6a882c31c">add LocalInit sanitizer</a>. 2018-06-22. URL: <a href="https://github.com/AndroidHardeningArchive/platform_external_clang/commit/776a0955ef6686d23a82d2e6a3cbd4a6a882c31c">https://github.com/AndroidHardeningArchive/platform_external_clang/commit/776a0955ef6686d23a82d2e6a3cbd4a6a882c31c</a>
   <dt id="biblio-n1793">[N1793]
   <dd>Freek Wiedijk; Robbert Krebbers. <a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1793.pdf">Stability of indeterminate values in C11</a>. URL: <a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1793.pdf">https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1793.pdf</a>
   <dt id="biblio-nat">[NaT]
   <dd>Raymond Chen. <a href="https://devblogs.microsoft.com/oldnewthing/20040119-00/?p=41003">Uninitialized garbage on ia64 can be deadly</a>. 2004-01-19. URL: <a href="https://devblogs.microsoft.com/oldnewthing/20040119-00/?p=41003">https://devblogs.microsoft.com/oldnewthing/20040119-00/?p=41003</a>
   <dt id="biblio-p0146r1">[P0146r1]
   <dd>Matt Calabrese. <a href="https://wg21.link/p0146r1">Regular Void</a>. 11 February 2016. URL: <a href="https://wg21.link/p0146r1">https://wg21.link/p0146r1</a>
   <dt id="biblio-p0632r0">[P0632r0]
   <dd>Jonathan Müller. <a href="https://wg21.link/p0632r0">Proposal of [[uninitialized]] attribute</a>. 19 January 2017. URL: <a href="https://wg21.link/p0632r0">https://wg21.link/p0632r0</a>
   <dt id="biblio-p2687r0">[P2687r0]
   <dd>Bjarne Stroustrup, Gabriel Dos Reis. <a href="https://wg21.link/p2687r0">Design Alternatives for Type-and-Resource Safe C++</a>. 15 October 2022. URL: <a href="https://wg21.link/p2687r0">https://wg21.link/p2687r0</a>
   <dt id="biblio-p2723r0">[P2723r0]
   <dd>JF Bastien. <a href="https://wg21.link/p2723r0">Zero-initialize objects of automatic storage duration</a>. 16 November 2022. URL: <a href="https://wg21.link/p2723r0">https://wg21.link/p2723r0</a>
   <dt id="biblio-randomness">[Randomness]
   <dd>Xi Wang. <a href="https://kqueue.org/blog/2012/06/25/more-randomness-or-less/">More randomness or less</a>. 2012-06-25. URL: <a href="https://kqueue.org/blog/2012/06/25/more-randomness-or-less/">https://kqueue.org/blog/2012/06/25/more-randomness-or-less/</a>
   <dt id="biblio-seacord">[Seacord]
   <dd>Robert C. Seacord. <a href="https://queue.acm.org/detail.cfm?id=3041020">Uninitialized Reads: Understanding the proposed revisions to the C language</a>. 2017-01-16. URL: <a href="https://queue.acm.org/detail.cfm?id=3041020">https://queue.acm.org/detail.cfm?id=3041020</a>
   <dt id="biblio-trap">[Trap]
   <dd>Richard Smith. <a href="https://reviews.llvm.org/D79249">[NOT FOR REVIEW] Experimental support for zero-or-trap behavior for uninitialized variables</a>. 2020-05-01. URL: <a href="https://reviews.llvm.org/D79249">https://reviews.llvm.org/D79249</a>
   <dt id="biblio-winkernel">[WinKernel]
   <dd>Joseph Bialek. <a href="https://twitter.com/JosephBialek/status/1062774315098112001">Join the Windows kernel in wishing farewell to uninitialized plain-old-data structs on the stack</a>. 2018-11-14. URL: <a href="https://twitter.com/JosephBialek/status/1062774315098112001">https://twitter.com/JosephBialek/status/1062774315098112001</a>
   <dt id="biblio-xnuheap">[XNUHeap]
   <dd>Apple Security Engineering and Architecture. <a href="https://security.apple.com/blog/towards-the-next-generation-of-xnu-memory-safety/">Towards the next generation of XNU memory safety: kalloc_type</a>. 2022-10-22. URL: <a href="https://security.apple.com/blog/towards-the-next-generation-of-xnu-memory-safety/">https://security.apple.com/blog/towards-the-next-generation-of-xnu-memory-safety/</a>
   <dt id="biblio-zeroing">[Zeroing]
   <dd>Xi Yang; et al. <a href="https://users.elis.ugent.be/~jsartor/researchDocs/OOPSLA2011Zero-submit.pdf">Why Nothing Matters: The Impact of Zeroing</a>. 2011-10. URL: <a href="https://users.elis.ugent.be/~jsartor/researchDocs/OOPSLA2011Zero-submit.pdf">https://users.elis.ugent.be/~jsartor/researchDocs/OOPSLA2011Zero-submit.pdf</a>
  </dl>