Tue, 06 Jan 2015 21:39:09 +0100
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 /* Cast operations to supplement the built-in casting operations. */
9 #ifndef mozilla_Casting_h
10 #define mozilla_Casting_h
12 #include "mozilla/Assertions.h"
13 #include "mozilla/TypeTraits.h"
15 #include <limits.h>
17 namespace mozilla {
19 /**
20 * Return a value of type |To|, containing the underlying bit pattern of |from|.
21 *
22 * |To| and |From| must be types of the same size; be careful of cross-platform
23 * size differences, or this might fail to compile on some but not all
24 * platforms.
25 */
26 template<typename To, typename From>
27 inline To
28 BitwiseCast(const From from)
29 {
30 static_assert(sizeof(From) == sizeof(To),
31 "To and From must have the same size");
32 union {
33 From from;
34 To to;
35 } u;
36 u.from = from;
37 return u.to;
38 }
40 namespace detail {
42 enum ToSignedness { ToIsSigned, ToIsUnsigned };
43 enum FromSignedness { FromIsSigned, FromIsUnsigned };
45 template<typename From,
46 typename To,
47 FromSignedness = IsSigned<From>::value ? FromIsSigned : FromIsUnsigned,
48 ToSignedness = IsSigned<To>::value ? ToIsSigned : ToIsUnsigned>
49 struct BoundsCheckImpl;
51 // Implicit conversions on operands to binary operations make this all a bit
52 // hard to verify. Attempt to ease the pain below by *only* comparing values
53 // that are obviously the same type (and will undergo no further conversions),
54 // even when it's not strictly necessary, for explicitness.
56 enum UUComparison { FromIsBigger, FromIsNotBigger };
58 // Unsigned-to-unsigned range check
60 template<typename From, typename To,
61 UUComparison = (sizeof(From) > sizeof(To)) ? FromIsBigger : FromIsNotBigger>
62 struct UnsignedUnsignedCheck;
64 template<typename From, typename To>
65 struct UnsignedUnsignedCheck<From, To, FromIsBigger>
66 {
67 public:
68 static bool checkBounds(const From from) {
69 return from <= From(To(-1));
70 }
71 };
73 template<typename From, typename To>
74 struct UnsignedUnsignedCheck<From, To, FromIsNotBigger>
75 {
76 public:
77 static bool checkBounds(const From from) {
78 return true;
79 }
80 };
82 template<typename From, typename To>
83 struct BoundsCheckImpl<From, To, FromIsUnsigned, ToIsUnsigned>
84 {
85 public:
86 static bool checkBounds(const From from) {
87 return UnsignedUnsignedCheck<From, To>::checkBounds(from);
88 }
89 };
91 // Signed-to-unsigned range check
93 template<typename From, typename To>
94 struct BoundsCheckImpl<From, To, FromIsSigned, ToIsUnsigned>
95 {
96 public:
97 static bool checkBounds(const From from) {
98 if (from < 0)
99 return false;
100 if (sizeof(To) >= sizeof(From))
101 return true;
102 return from <= From(To(-1));
103 }
104 };
106 // Unsigned-to-signed range check
108 enum USComparison { FromIsSmaller, FromIsNotSmaller };
110 template<typename From, typename To,
111 USComparison = (sizeof(From) < sizeof(To)) ? FromIsSmaller : FromIsNotSmaller>
112 struct UnsignedSignedCheck;
114 template<typename From, typename To>
115 struct UnsignedSignedCheck<From, To, FromIsSmaller>
116 {
117 public:
118 static bool checkBounds(const From from) {
119 return true;
120 }
121 };
123 template<typename From, typename To>
124 struct UnsignedSignedCheck<From, To, FromIsNotSmaller>
125 {
126 public:
127 static bool checkBounds(const From from) {
128 const To MaxValue = To((1ULL << (CHAR_BIT * sizeof(To) - 1)) - 1);
129 return from <= From(MaxValue);
130 }
131 };
133 template<typename From, typename To>
134 struct BoundsCheckImpl<From, To, FromIsUnsigned, ToIsSigned>
135 {
136 public:
137 static bool checkBounds(const From from) {
138 return UnsignedSignedCheck<From, To>::checkBounds(from);
139 }
140 };
142 // Signed-to-signed range check
144 template<typename From, typename To>
145 struct BoundsCheckImpl<From, To, FromIsSigned, ToIsSigned>
146 {
147 public:
148 static bool checkBounds(const From from) {
149 if (sizeof(From) <= sizeof(To))
150 return true;
151 const To MaxValue = To((1ULL << (CHAR_BIT * sizeof(To) - 1)) - 1);
152 const To MinValue = -MaxValue - To(1);
153 return From(MinValue) <= from &&
154 From(from) <= From(MaxValue);
155 }
156 };
158 template<typename From, typename To,
159 bool TypesAreIntegral = IsIntegral<From>::value && IsIntegral<To>::value>
160 class BoundsChecker;
162 template<typename From>
163 class BoundsChecker<From, From, true>
164 {
165 public:
166 static bool checkBounds(const From from) { return true; }
167 };
169 template<typename From, typename To>
170 class BoundsChecker<From, To, true>
171 {
172 public:
173 static bool checkBounds(const From from) {
174 return BoundsCheckImpl<From, To>::checkBounds(from);
175 }
176 };
178 template<typename From, typename To>
179 inline bool
180 IsInBounds(const From from)
181 {
182 return BoundsChecker<From, To>::checkBounds(from);
183 }
185 } // namespace detail
187 /**
188 * Cast a value of integral type |From| to a value of integral type |To|,
189 * asserting that the cast will be a safe cast per C++ (that is, that |to| is in
190 * the range of values permitted for the type |From|).
191 */
192 template<typename To, typename From>
193 inline To
194 SafeCast(const From from)
195 {
196 MOZ_ASSERT((detail::IsInBounds<From, To>(from)));
197 return static_cast<To>(from);
198 }
200 } // namespace mozilla
202 #endif /* mozilla_Casting_h */