From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 204AC3857429; Tue, 12 Oct 2021 15:56:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 204AC3857429 From: "ott at fb dot com" To: gcc-bugs@gcc.gnu.org Subject: [Bug libstdc++/102712] New: std::optional::operator* should assert on unset value Date: Tue, 12 Oct 2021 15:56:19 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: libstdc++ X-Bugzilla-Version: unknown X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: ott at fb dot com X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Oct 2021 15:56:20 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D102712 Bug ID: 102712 Summary: std::optional::operator* should assert on unset value Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: ott at fb dot com Target Milestone: --- It is UB to call operator* on an unset std::optional, and when doing so it = is easy to hit time-traveling UB, resulting in behavior that is very hard to debug.=20 For example, setting a field of an unset optional with operator-> may look = like it succeeded, and the rest of the program will behave as if the optional was set, but it will silently leak memory because the destructor won't run. Ano= ther plausible scenario is having an optional where X has an operator bool(),= and spelling "if (*opt)" when the intention is to spell "if (opt)". The program compiles and the optional is just assumed set around the condition. Even UBSan with some of the strictest settings doesn't detect this. All major implementations of the type have defined behavior in debug builds: - libc++ asserts https://github.com/llvm-mirror/libcxx/blob/master/include/optional#L905 - boost asserts https://github.com/boostorg/optional/blob/develop/include/boost/optional/op= tional.hpp#L1213 - abseil asserts https://github.com/abseil/abseil-cpp/blob/master/absl/types/optional.h#L428 - folly throws (in any compilation mode) https://github.com/facebook/folly/blob/master/folly/Optional.h#L330 https://github.com/facebook/folly/blob/master/folly/Optional.h#L297 So anyone migrating from any of these is in for a world of hurt.=20 Please consider adding an assertion in libstdc++.=