Changeset 233577 in webkit


Ignore:
Timestamp:
Jul 6, 2018 4:49:39 AM (6 years ago)
Author:
fred.wang@free.fr
Message:

WTF's internal std::optional implementation should abort() on bad optional access
https://bugs.webkit.org/show_bug.cgi?id=186536

Patch by Frederic Wang <fwang@igalia.com> on 2018-07-06
Reviewed by Michael Catanzaro.

Currently, some ports built with recent compilers will cause the program to abort when one
tries to access the value of an unset std:optional (i.e. std::nullopt) as specified by C++17.
However, most ports still use WTF's internal std::optional implementation, which does not
verify illegal access. Hence it's not possible for developers working on these ports to
detect issues like bugs #186189, #186535, #186752, #186753, #187139, #187145, #187243 or
#187382.
WTF's version of std::optional was introduced in bug #164199 but it was not possible to
verify the availability of the value inside constexpr member functions because the assert
might involve asm declarations. This commit introduces a new ASSERT_UNDER_CONSTEXPR_CONTEXT
macro (a simplified version of ASSERT that can be used in constexpr context) and uses it in
WTF's implementation of std::optional.

  • wtf/Assertions.h: Define ASSERT_UNDER_CONSTEXPR_CONTEXT as a version of ASSERT that can be

used in constexpr context (in particular avoids asm declarations).

  • wtf/Optional.h:

(std::optional::operator ->): Add an assert to ensure the optional value is available.
(std::optional::operator *): Ditto.
(std::optional::value const): Ditto.
(std::optional::value): Ditto.
(std::optional<T::value const): Ditto.

Location:
trunk/Source/WTF
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r233542 r233577  
     12018-07-06  Frederic Wang  <fwang@igalia.com>
     2
     3        WTF's internal std::optional implementation should abort() on bad optional access
     4        https://bugs.webkit.org/show_bug.cgi?id=186536
     5
     6        Reviewed by Michael Catanzaro.
     7
     8        Currently, some ports built with recent compilers will cause the program to abort when one
     9        tries to access the value of an unset std:optional (i.e. std::nullopt) as specified by C++17.
     10        However, most ports still use WTF's internal std::optional implementation, which does not
     11        verify illegal access. Hence it's not possible for developers working on these ports to
     12        detect issues like bugs #186189, #186535, #186752, #186753, #187139, #187145, #187243 or
     13        #187382.
     14        WTF's version of std::optional was introduced in bug #164199 but it was not possible to
     15        verify the availability of the value inside constexpr member functions because the assert
     16        might involve asm declarations. This commit introduces a new ASSERT_UNDER_CONSTEXPR_CONTEXT
     17        macro (a simplified version of ASSERT that can be used in constexpr context) and uses it in
     18        WTF's implementation of std::optional.
     19
     20        * wtf/Assertions.h: Define ASSERT_UNDER_CONSTEXPR_CONTEXT as a version of ASSERT that can be
     21        used in constexpr context (in particular avoids asm declarations).
     22        * wtf/Optional.h:
     23        (std::optional::operator ->): Add an assert to ensure the optional value is available.
     24        (std::optional::operator *): Ditto.
     25        (std::optional::value const): Ditto.
     26        (std::optional::value): Ditto.
     27        (std::optional<T::value const): Ditto.
     28
    1292018-07-05  Commit Queue  <commit-queue@webkit.org>
    230
  • trunk/Source/WTF/wtf/Assertions.h

    r233542 r233577  
    221221#endif
    222222
     223#if COMPILER(MSVC)
     224#define WTFBreakpointTrapUnderConstexprContext() __debugbreak()
     225#else
     226#define WTFBreakpointTrapUnderConstexprContext() __builtin_trap()
     227#endif
     228
    223229#ifndef CRASH
    224230
     
    231237    __builtin_unreachable(); \
    232238} while (0)
     239#define CRASH_UNDER_CONSTEXPR_CONTEXT() do { \
     240    WTFBreakpointTrapUnderConstexprContext(); \
     241    __builtin_unreachable(); \
     242} while (0)
    233243#else
    234244#define CRASH() WTFCrash()
     245#define CRASH_UNDER_CONSTEXPR_CONTEXT() WTFCrash()
    235246#endif
    236247
     
    280291
    281292#define ASSERT(assertion) ((void)0)
     293#define ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) ((void)0)
    282294#define ASSERT_AT(assertion, file, line, function) ((void)0)
    283295#define ASSERT_NOT_REACHED() ((void)0)
     
    307319        WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
    308320        CRASH(); \
     321    } \
     322} while (0)
     323
     324#define ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) do { \
     325    if (!(assertion)) { \
     326        WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
     327        CRASH_UNDER_CONSTEXPR_CONTEXT(); \
    309328    } \
    310329} while (0)
  • trunk/Source/WTF/wtf/Optional.h

    r233542 r233577  
    531531
    532532  OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() {
    533     // FIXME: We need to offer special assert function that can be used under the contexpr context.
    534     // CONSTEXPR_ASSERT(initialized());
     533    ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
    535534    return dataptr();
    536535  }
     
    541540
    542541  OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & {
    543     // FIXME: We need to offer special assert function that can be used under the contexpr context.
    544     // CONSTEXPR_ASSERT(initialized());
     542    ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
    545543    return contained_val();
    546544  }
    547545
    548546  OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && {
    549     // FIXME: We need to offer special assert function that can be used under the contexpr context.
    550     // CONSTEXPR_ASSERT(initialized());
     547    ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
    551548    return detail_::constexpr_move(contained_val());
    552549  }
    553550
    554551  constexpr T const& value() const& {
    555     // FIXME: We need to offer special assert function that can be used under the contexpr context.
    556     // return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
     552    ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
    557553    return contained_val();
    558554  }
    559555
    560556  OPTIONAL_MUTABLE_CONSTEXPR T& value() & {
    561     // FIXME: We need to offer special assert function that can be used under the contexpr context.
    562     // return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
     557    ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
    563558    return contained_val();
    564559  }
    565560
    566561  OPTIONAL_MUTABLE_CONSTEXPR T&& value() && {
    567     // FIXME: We need to offer special assert function that can be used under the contexpr context.
    568     // if (!initialized()) __THROW_EXCEPTION(bad_optional_access("bad optional access"));
     562    ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
    569563    return std::move(contained_val());
    570564  }
     
    684678
    685679  constexpr T& value() const {
    686     // FIXME: We need to offer special assert function that can be used under the contexpr context.
    687     // return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref);
     680    ASSERT_UNDER_CONSTEXPR_CONTEXT(ref());
    688681    return *ref;
    689682  }
Note: See TracChangeset for help on using the changeset viewer.