mfbt/Assertions.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 /* Implementations of runtime and static assertion macros for C and C++. */
     9 #ifndef mozilla_Assertions_h
    10 #define mozilla_Assertions_h
    12 #include "mozilla/Attributes.h"
    13 #include "mozilla/Compiler.h"
    14 #include "mozilla/Likely.h"
    15 #include "mozilla/MacroArgs.h"
    17 #include <stddef.h>
    18 #include <stdio.h>
    19 #include <stdlib.h>
    20 #ifdef WIN32
    21    /*
    22     * TerminateProcess and GetCurrentProcess are defined in <winbase.h>, which
    23     * further depends on <windef.h>.  We hardcode these few definitions manually
    24     * because those headers clutter the global namespace with a significant
    25     * number of undesired macros and symbols.
    26     */
    27 #  ifdef __cplusplus
    28    extern "C" {
    29 #  endif
    30    __declspec(dllimport) int __stdcall
    31    TerminateProcess(void* hProcess, unsigned int uExitCode);
    32    __declspec(dllimport) void* __stdcall GetCurrentProcess(void);
    33 #  ifdef __cplusplus
    34    }
    35 #  endif
    36 #else
    37 #  include <signal.h>
    38 #endif
    39 #ifdef ANDROID
    40 #  include <android/log.h>
    41 #endif
    43 /*
    44  * MOZ_STATIC_ASSERT may be used to assert a condition *at compile time* in C.
    45  * In C++11, static_assert is provided by the compiler to the same effect.
    46  * This can be useful when you make certain assumptions about what must hold for
    47  * optimal, or even correct, behavior.  For example, you might assert that the
    48  * size of a struct is a multiple of the target architecture's word size:
    49  *
    50  *   struct S { ... };
    51  *   // C
    52  *   MOZ_STATIC_ASSERT(sizeof(S) % sizeof(size_t) == 0,
    53  *                     "S should be a multiple of word size for efficiency");
    54  *   // C++11
    55  *   static_assert(sizeof(S) % sizeof(size_t) == 0,
    56  *                 "S should be a multiple of word size for efficiency");
    57  *
    58  * This macro can be used in any location where both an extern declaration and a
    59  * typedef could be used.
    60  */
    61 #ifndef __cplusplus
    62    /*
    63     * Some of the definitions below create an otherwise-unused typedef.  This
    64     * triggers compiler warnings with some versions of gcc, so mark the typedefs
    65     * as permissibly-unused to disable the warnings.
    66     */
    67 #  if defined(__GNUC__)
    68 #    define MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
    69 #  else
    70 #    define MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE /* nothing */
    71 #  endif
    72 #  define MOZ_STATIC_ASSERT_GLUE1(x, y)          x##y
    73 #  define MOZ_STATIC_ASSERT_GLUE(x, y)           MOZ_STATIC_ASSERT_GLUE1(x, y)
    74 #  if defined(__SUNPRO_CC)
    75      /*
    76       * The Sun Studio C++ compiler is buggy when declaring, inside a function,
    77       * another extern'd function with an array argument whose length contains a
    78       * sizeof, triggering the error message "sizeof expression not accepted as
    79       * size of array parameter".  This bug (6688515, not public yet) would hit
    80       * defining moz_static_assert as a function, so we always define an extern
    81       * array for Sun Studio.
    82       *
    83       * We include the line number in the symbol name in a best-effort attempt
    84       * to avoid conflicts (see below).
    85       */
    86 #    define MOZ_STATIC_ASSERT(cond, reason) \
    87        extern char MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)[(cond) ? 1 : -1]
    88 #  elif defined(__COUNTER__)
    89      /*
    90       * If there was no preferred alternative, use a compiler-agnostic version.
    91       *
    92       * Note that the non-__COUNTER__ version has a bug in C++: it can't be used
    93       * in both |extern "C"| and normal C++ in the same translation unit.  (Alas
    94       * |extern "C"| isn't allowed in a function.)  The only affected compiler
    95       * we really care about is gcc 4.2.  For that compiler and others like it,
    96       * we include the line number in the function name to do the best we can to
    97       * avoid conflicts.  These should be rare: a conflict would require use of
    98       * MOZ_STATIC_ASSERT on the same line in separate files in the same
    99       * translation unit, *and* the uses would have to be in code with
   100       * different linkage, *and* the first observed use must be in C++-linkage
   101       * code.
   102       */
   103 #    define MOZ_STATIC_ASSERT(cond, reason) \
   104        typedef int MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __COUNTER__)[(cond) ? 1 : -1] MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE
   105 #  else
   106 #    define MOZ_STATIC_ASSERT(cond, reason) \
   107        extern void MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)(int arg[(cond) ? 1 : -1]) MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE
   108 #  endif
   110 #define MOZ_STATIC_ASSERT_IF(cond, expr, reason)  MOZ_STATIC_ASSERT(!(cond) || (expr), reason)
   111 #else
   112 #define MOZ_STATIC_ASSERT_IF(cond, expr, reason)  static_assert(!(cond) || (expr), reason)
   113 #endif
   115 #ifdef __cplusplus
   116 extern "C" {
   117 #endif
   119 /*
   120  * Prints |s| as an assertion failure (using file and ln as the location of the
   121  * assertion) to the standard debug-output channel.
   122  *
   123  * Usually you should use MOZ_ASSERT or MOZ_CRASH instead of this method.  This
   124  * method is primarily for internal use in this header, and only secondarily
   125  * for use in implementing release-build assertions.
   126  */
   127 static MOZ_ALWAYS_INLINE void
   128 MOZ_ReportAssertionFailure(const char* s, const char* file, int ln)
   129 {
   130 #ifdef ANDROID
   131   __android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert",
   132                       "Assertion failure: %s, at %s:%d\n", s, file, ln);
   133 #else
   134   fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
   135   fflush(stderr);
   136 #endif
   137 }
   139 static MOZ_ALWAYS_INLINE void
   140 MOZ_ReportCrash(const char* s, const char* file, int ln)
   141 {
   142 #ifdef ANDROID
   143     __android_log_print(ANDROID_LOG_FATAL, "MOZ_CRASH",
   144                         "Hit MOZ_CRASH(%s) at %s:%d\n", s, file, ln);
   145 #else
   146   fprintf(stderr, "Hit MOZ_CRASH(%s) at %s:%d\n", s, file, ln);
   147   fflush(stderr);
   148 #endif
   149 }
   151 /**
   152  * MOZ_REALLY_CRASH is used in the implementation of MOZ_CRASH().  You should
   153  * call MOZ_CRASH instead.
   154  */
   155 #if defined(_MSC_VER)
   156    /*
   157     * On MSVC use the __debugbreak compiler intrinsic, which produces an inline
   158     * (not nested in a system function) breakpoint.  This distinctively invokes
   159     * Breakpad without requiring system library symbols on all stack-processing
   160     * machines, as a nested breakpoint would require.
   161     *
   162     * We use TerminateProcess with the exit code aborting would generate
   163     * because we don't want to invoke atexit handlers, destructors, library
   164     * unload handlers, and so on when our process might be in a compromised
   165     * state.
   166     *
   167     * We don't use abort() because it'd cause Windows to annoyingly pop up the
   168     * process error dialog multiple times.  See bug 345118 and bug 426163.
   169     *
   170     * We follow TerminateProcess() with a call to MOZ_NoReturn() so that the
   171     * compiler doesn't hassle us to provide a return statement after a
   172     * MOZ_REALLY_CRASH() call.
   173     *
   174     * (Technically these are Windows requirements, not MSVC requirements.  But
   175     * practically you need MSVC for debugging, and we only ship builds created
   176     * by MSVC, so doing it this way reduces complexity.)
   177     */
   179 __declspec(noreturn) __inline void MOZ_NoReturn() {}
   181 #  ifdef __cplusplus
   182 #    define MOZ_REALLY_CRASH() \
   183        do { \
   184          ::__debugbreak(); \
   185          *((volatile int*) NULL) = 123; \
   186          ::TerminateProcess(::GetCurrentProcess(), 3); \
   187          ::MOZ_NoReturn(); \
   188        } while (0)
   189 #  else
   190 #    define MOZ_REALLY_CRASH() \
   191        do { \
   192          __debugbreak(); \
   193          *((volatile int*) NULL) = 123; \
   194          TerminateProcess(GetCurrentProcess(), 3); \
   195          MOZ_NoReturn(); \
   196        } while (0)
   197 #  endif
   198 #else
   199 #  ifdef __cplusplus
   200 #    define MOZ_REALLY_CRASH() \
   201        do { \
   202          *((volatile int*) NULL) = 123; \
   203          ::abort(); \
   204        } while (0)
   205 #  else
   206 #    define MOZ_REALLY_CRASH() \
   207        do { \
   208          *((volatile int*) NULL) = 123; \
   209          abort(); \
   210        } while (0)
   211 #  endif
   212 #endif
   214 /*
   215  * MOZ_CRASH([explanation-string]) crashes the program, plain and simple, in a
   216  * Breakpad-compatible way, in both debug and release builds.
   217  *
   218  * MOZ_CRASH is a good solution for "handling" failure cases when you're
   219  * unwilling or unable to handle them more cleanly -- for OOM, for likely memory
   220  * corruption, and so on.  It's also a good solution if you need safe behavior
   221  * in release builds as well as debug builds.  But if the failure is one that
   222  * should be debugged and fixed, MOZ_ASSERT is generally preferable.
   223  *
   224  * The optional explanation-string, if provided, must be a string literal
   225  * explaining why we're crashing.  This argument is intended for use with
   226  * MOZ_CRASH() calls whose rationale is non-obvious; don't use it if it's
   227  * obvious why we're crashing.
   228  *
   229  * If we're a DEBUG build and we crash at a MOZ_CRASH which provides an
   230  * explanation-string, we print the string to stderr.  Otherwise, we don't
   231  * print anything; this is because we want MOZ_CRASH to be 100% safe in release
   232  * builds, and it's hard to print to stderr safely when memory might have been
   233  * corrupted.
   234  */
   235 #ifndef DEBUG
   236 #  define MOZ_CRASH(...) MOZ_REALLY_CRASH()
   237 #else
   238 #  define MOZ_CRASH(...) \
   239      do { \
   240        MOZ_ReportCrash("" __VA_ARGS__, __FILE__, __LINE__); \
   241        MOZ_REALLY_CRASH(); \
   242      } while(0)
   243 #endif
   245 #ifdef __cplusplus
   246 } /* extern "C" */
   247 #endif
   249 /*
   250  * MOZ_ASSERT(expr [, explanation-string]) asserts that |expr| must be truthy in
   251  * debug builds.  If it is, execution continues.  Otherwise, an error message
   252  * including the expression and the explanation-string (if provided) is printed,
   253  * an attempt is made to invoke any existing debugger, and execution halts.
   254  * MOZ_ASSERT is fatal: no recovery is possible.  Do not assert a condition
   255  * which can correctly be falsy.
   256  *
   257  * The optional explanation-string, if provided, must be a string literal
   258  * explaining the assertion.  It is intended for use with assertions whose
   259  * correctness or rationale is non-obvious, and for assertions where the "real"
   260  * condition being tested is best described prosaically.  Don't provide an
   261  * explanation if it's not actually helpful.
   262  *
   263  *   // No explanation needed: pointer arguments often must not be NULL.
   264  *   MOZ_ASSERT(arg);
   265  *
   266  *   // An explanation can be helpful to explain exactly how we know an
   267  *   // assertion is valid.
   268  *   MOZ_ASSERT(state == WAITING_FOR_RESPONSE,
   269  *              "given that <thingA> and <thingB>, we must have...");
   270  *
   271  *   // Or it might disambiguate multiple identical (save for their location)
   272  *   // assertions of the same expression.
   273  *   MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(),
   274  *              "we already set [[PrimitiveThis]] for this Boolean object");
   275  *   MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(),
   276  *              "we already set [[PrimitiveThis]] for this String object");
   277  *
   278  * MOZ_ASSERT has no effect in non-debug builds.  It is designed to catch bugs
   279  * *only* during debugging, not "in the field". If you want the latter, use
   280  * MOZ_RELEASE_ASSERT, which applies to non-debug builds as well.
   281  */
   283 /* First the single-argument form. */
   284 #define MOZ_ASSERT_HELPER1(expr) \
   285    do { \
   286      if (MOZ_UNLIKELY(!(expr))) { \
   287        MOZ_ReportAssertionFailure(#expr, __FILE__, __LINE__); \
   288        MOZ_REALLY_CRASH(); \
   289      } \
   290    } while (0)
   291 /* Now the two-argument form. */
   292 #define MOZ_ASSERT_HELPER2(expr, explain) \
   293    do { \
   294      if (MOZ_UNLIKELY(!(expr))) { \
   295        MOZ_ReportAssertionFailure(#expr " (" explain ")", __FILE__, __LINE__); \
   296        MOZ_REALLY_CRASH(); \
   297      } \
   298    } while (0)
   300 #define MOZ_RELEASE_ASSERT_GLUE(a, b) a b
   301 #define MOZ_RELEASE_ASSERT(...) \
   302    MOZ_RELEASE_ASSERT_GLUE( \
   303      MOZ_PASTE_PREFIX_AND_ARG_COUNT(MOZ_ASSERT_HELPER, __VA_ARGS__), \
   304      (__VA_ARGS__))
   306 #ifdef DEBUG
   307 #  define MOZ_ASSERT(...) MOZ_RELEASE_ASSERT(__VA_ARGS__)
   308 #else
   309 #  define MOZ_ASSERT(...) do { } while(0)
   310 #endif /* DEBUG */
   312 /*
   313  * MOZ_ASSERT_IF(cond1, cond2) is equivalent to MOZ_ASSERT(cond2) if cond1 is
   314  * true.
   315  *
   316  *   MOZ_ASSERT_IF(isPrime(num), num == 2 || isOdd(num));
   317  *
   318  * As with MOZ_ASSERT, MOZ_ASSERT_IF has effect only in debug builds.  It is
   319  * designed to catch bugs during debugging, not "in the field".
   320  */
   321 #ifdef DEBUG
   322 #  define MOZ_ASSERT_IF(cond, expr) \
   323      do { \
   324        if (cond) \
   325          MOZ_ASSERT(expr); \
   326      } while (0)
   327 #else
   328 #  define MOZ_ASSERT_IF(cond, expr)  do { } while (0)
   329 #endif
   331 /*
   332  * MOZ_ASSUME_UNREACHABLE_MARKER() expands to an expression which states that it is
   333  * undefined behavior for execution to reach this point.  No guarantees are made
   334  * about what will happen if this is reached at runtime.  Most code should
   335  * probably use the higher level MOZ_ASSUME_UNREACHABLE, which uses this when
   336  * appropriate.
   337  */
   338 #if defined(__clang__)
   339 #  define MOZ_ASSUME_UNREACHABLE_MARKER() __builtin_unreachable()
   340 #elif defined(__GNUC__)
   341    /*
   342     * __builtin_unreachable() was implemented in gcc 4.5.  If we don't have
   343     * that, call a noreturn function; abort() will do nicely.  Qualify the call
   344     * in C++ in case there's another abort() visible in local scope.
   345     */
   346 #  if MOZ_GCC_VERSION_AT_LEAST(4, 5, 0)
   347 #    define MOZ_ASSUME_UNREACHABLE_MARKER() __builtin_unreachable()
   348 #  else
   349 #    ifdef __cplusplus
   350 #      define MOZ_ASSUME_UNREACHABLE_MARKER() ::abort()
   351 #    else
   352 #      define MOZ_ASSUME_UNREACHABLE_MARKER() abort()
   353 #    endif
   354 #  endif
   355 #elif defined(_MSC_VER)
   356 #  define MOZ_ASSUME_UNREACHABLE_MARKER() __assume(0)
   357 #else
   358 #  ifdef __cplusplus
   359 #    define MOZ_ASSUME_UNREACHABLE_MARKER() ::abort()
   360 #  else
   361 #    define MOZ_ASSUME_UNREACHABLE_MARKER() abort()
   362 #  endif
   363 #endif
   365 /*
   366  * MOZ_ASSUME_UNREACHABLE([reason]) tells the compiler that it can assume that
   367  * the macro call cannot be reached during execution.  This lets the compiler
   368  * generate better-optimized code under some circumstances, at the expense of
   369  * the program's behavior being undefined if control reaches the
   370  * MOZ_ASSUME_UNREACHABLE.
   371  *
   372  * In Gecko, you probably should not use this macro outside of performance- or
   373  * size-critical code, because it's unsafe.  If you don't care about code size
   374  * or performance, you should probably use MOZ_ASSERT or MOZ_CRASH.
   375  *
   376  * SpiderMonkey is a different beast, and there it's acceptable to use
   377  * MOZ_ASSUME_UNREACHABLE more widely.
   378  *
   379  * Note that MOZ_ASSUME_UNREACHABLE is noreturn, so it's valid not to return a
   380  * value following a MOZ_ASSUME_UNREACHABLE call.
   381  *
   382  * Example usage:
   383  *
   384  *   enum ValueType {
   385  *     VALUE_STRING,
   386  *     VALUE_INT,
   387  *     VALUE_FLOAT
   388  *   };
   389  *
   390  *   int ptrToInt(ValueType type, void* value) {
   391  *   {
   392  *     // We know for sure that type is either INT or FLOAT, and we want this
   393  *     // code to run as quickly as possible.
   394  *     switch (type) {
   395  *     case VALUE_INT:
   396  *       return *(int*) value;
   397  *     case VALUE_FLOAT:
   398  *       return (int) *(float*) value;
   399  *     default:
   400  *       MOZ_ASSUME_UNREACHABLE("can only handle VALUE_INT and VALUE_FLOAT");
   401  *     }
   402  *   }
   403  */
   404 #if defined(DEBUG)
   405 #  define MOZ_ASSUME_UNREACHABLE(...) \
   406      do { \
   407        MOZ_ASSERT(false, "MOZ_ASSUME_UNREACHABLE(" __VA_ARGS__ ")"); \
   408        MOZ_ASSUME_UNREACHABLE_MARKER(); \
   409      } while (0)
   410 #else
   411 #  define MOZ_ASSUME_UNREACHABLE(reason)  MOZ_ASSUME_UNREACHABLE_MARKER()
   412 #endif
   414 /*
   415  * MOZ_ALWAYS_TRUE(expr) and MOZ_ALWAYS_FALSE(expr) always evaluate the provided
   416  * expression, in debug builds and in release builds both.  Then, in debug
   417  * builds only, the value of the expression is asserted either true or false
   418  * using MOZ_ASSERT.
   419  */
   420 #ifdef DEBUG
   421 #  define MOZ_ALWAYS_TRUE(expr)      MOZ_ASSERT((expr))
   422 #  define MOZ_ALWAYS_FALSE(expr)     MOZ_ASSERT(!(expr))
   423 #else
   424 #  define MOZ_ALWAYS_TRUE(expr)      ((void)(expr))
   425 #  define MOZ_ALWAYS_FALSE(expr)     ((void)(expr))
   426 #endif
   428 #endif /* mozilla_Assertions_h */

mercurial