mfbt/GuardObjects.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /* Implementation of macros to ensure correct use of RAII Auto* objects. */
     9 #ifndef mozilla_GuardObjects_h
    10 #define mozilla_GuardObjects_h
    12 #include "mozilla/Assertions.h"
    13 #include "mozilla/NullPtr.h"
    14 #include "mozilla/Types.h"
    16 #ifdef __cplusplus
    18 #ifdef DEBUG
    20 namespace mozilla {
    21 namespace detail {
    23 /*
    24  * The following classes are designed to cause assertions to detect
    25  * inadvertent use of guard objects as temporaries. In other words,
    26  * when we have a guard object whose only purpose is its constructor and
    27  * destructor (and is never otherwise referenced), the intended use
    28  * might be:
    29  *
    30  *   AutoRestore savePainting(mIsPainting);
    31  *
    32  * but is is easy to accidentally write:
    33  *
    34  *   AutoRestore(mIsPainting);
    35  *
    36  * which compiles just fine, but runs the destructor well before the
    37  * intended time.
    38  *
    39  * They work by adding (#ifdef DEBUG) an additional parameter to the
    40  * guard object's constructor, with a default value, so that users of
    41  * the guard object's API do not need to do anything. The default value
    42  * of this parameter is a temporary object. C++ (ISO/IEC 14882:1998),
    43  * section 12.2 [class.temporary], clauses 4 and 5 seem to assume a
    44  * guarantee that temporaries are destroyed in the reverse of their
    45  * construction order, but I actually can't find a statement that that
    46  * is true in the general case (beyond the two specific cases mentioned
    47  * there). However, it seems to be true.
    48  *
    49  * These classes are intended to be used only via the macros immediately
    50  * below them:
    51  *
    52  *   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER declares (ifdef DEBUG) a member
    53  *     variable, and should be put where a declaration of a private
    54  *     member variable would be placed.
    55  *   MOZ_GUARD_OBJECT_NOTIFIER_PARAM should be placed at the end of the
    56  *     parameters to each constructor of the guard object; it declares
    57  *     (ifdef DEBUG) an additional parameter. (But use the *_ONLY_PARAM
    58  *     variant for constructors that take no other parameters.)
    59  *   MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL should likewise be used in
    60  *     the implementation of such constructors when they are not inline.
    61  *   MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT should be used in
    62  *     the implementation of such constructors to pass the parameter to
    63  *     a base class that also uses these macros
    64  *   MOZ_GUARD_OBJECT_NOTIFIER_INIT is a statement that belongs in each
    65  *     constructor. It uses the parameter declared by
    66  *     MOZ_GUARD_OBJECT_NOTIFIER_PARAM.
    67  *
    68  * For more details, and examples of using these macros, see
    69  * https://developer.mozilla.org/en/Using_RAII_classes_in_Mozilla
    70  */
    71 class GuardObjectNotifier
    72 {
    73   private:
    74     bool* statementDone;
    76   public:
    77     GuardObjectNotifier() : statementDone(nullptr) { }
    79     ~GuardObjectNotifier() {
    80       *statementDone = true;
    81     }
    83     void setStatementDone(bool* statementIsDone) {
    84       statementDone = statementIsDone;
    85     }
    86 };
    88 class GuardObjectNotificationReceiver
    89 {
    90   private:
    91     bool statementDone;
    93   public:
    94     GuardObjectNotificationReceiver() : statementDone(false) { }
    96     ~GuardObjectNotificationReceiver() {
    97       /*
    98        * Assert that the guard object was not used as a temporary.  (Note that
    99        * this assert might also fire if init is not called because the guard
   100        * object's implementation is not using the above macros correctly.)
   101        */
   102       MOZ_ASSERT(statementDone);
   103     }
   105     void init(const GuardObjectNotifier& constNotifier) {
   106       /*
   107        * constNotifier is passed as a const reference so that we can pass a
   108        * temporary, but we really intend it as non-const.
   109        */
   110       GuardObjectNotifier& notifier = const_cast<GuardObjectNotifier&>(constNotifier);
   111       notifier.setStatementDone(&statementDone);
   112     }
   113 };
   115 } /* namespace detail */
   116 } /* namespace mozilla */
   118 #endif /* DEBUG */
   120 #ifdef DEBUG
   121 #  define MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER \
   122      mozilla::detail::GuardObjectNotificationReceiver _mCheckNotUsedAsTemporary;
   123 #  define MOZ_GUARD_OBJECT_NOTIFIER_PARAM \
   124      , const mozilla::detail::GuardObjectNotifier& _notifier = \
   125          mozilla::detail::GuardObjectNotifier()
   126 #  define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM \
   127      const mozilla::detail::GuardObjectNotifier& _notifier = \
   128          mozilla::detail::GuardObjectNotifier()
   129 #  define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL \
   130      , const mozilla::detail::GuardObjectNotifier& _notifier
   131 #  define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL \
   132      const mozilla::detail::GuardObjectNotifier& _notifier
   133 #  define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT \
   134      , _notifier
   135 #  define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT \
   136        _notifier
   137 #  define MOZ_GUARD_OBJECT_NOTIFIER_INIT \
   138      do { _mCheckNotUsedAsTemporary.init(_notifier); } while (0)
   139 #else
   140 #  define MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   141 #  define MOZ_GUARD_OBJECT_NOTIFIER_PARAM
   142 #  define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM
   143 #  define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL
   144 #  define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL
   145 #  define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT
   146 #  define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
   147 #  define MOZ_GUARD_OBJECT_NOTIFIER_INIT do { } while (0)
   148 #endif
   150 #endif /* __cplusplus */
   152 #endif /* mozilla_GuardObjects_h */

mercurial