1 | /* |
2 | * Copyright (C) 2011, 2015 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 | * THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #include "config.h" |
27 | #include <wtf/CheckedArithmetic.h> |
28 | |
29 | namespace TestWebKitAPI { |
30 | |
31 | class OverflowCrashLogger { |
32 | protected: |
33 | void overflowed() |
34 | { |
35 | m_overflowCount++; |
36 | } |
37 | |
38 | void clearOverflow() |
39 | { |
40 | m_overflowCount = 0; |
41 | } |
42 | |
43 | static void crash() |
44 | { |
45 | s_didCrash = true; |
46 | } |
47 | |
48 | public: |
49 | void reset() |
50 | { |
51 | m_overflowCount = 0; |
52 | s_didCrash = false; |
53 | } |
54 | |
55 | bool hasOverflowed() const { return m_overflowCount > 0; } |
56 | int overflowCount() const { return m_overflowCount; } |
57 | |
58 | bool didCrash() const { return s_didCrash; } |
59 | |
60 | private: |
61 | int m_overflowCount { 0 }; |
62 | static bool s_didCrash; |
63 | }; |
64 | |
65 | bool OverflowCrashLogger::s_didCrash = false; |
66 | |
67 | template <typename type> |
68 | static void resetOverflow(Checked<type, OverflowCrashLogger>& value) |
69 | { |
70 | value.reset(); |
71 | value = 100; |
72 | value *= std::numeric_limits<type>::max(); |
73 | } |
74 | |
75 | #define CheckedArithmeticTest(type, Coercer, MixedSignednessTester) \ |
76 | TEST(WTF, Checked_##type) \ |
77 | { \ |
78 | typedef Coercer<type> CoercerType; \ |
79 | typedef MixedSignednessTester<type, CoercerType> MixedSignednessTesterType; \ |
80 | CheckedArithmeticTester<type, CoercerType, MixedSignednessTesterType>::run(); \ |
81 | } |
82 | |
83 | #define coerceLiteral(x) Coercer::coerce(x) |
84 | |
85 | template <typename type, typename Coercer, typename MixedSignednessTester> |
86 | class CheckedArithmeticTester { |
87 | public: |
88 | static void run() |
89 | { |
90 | Checked<type, RecordOverflow> value; |
91 | EXPECT_EQ(coerceLiteral(0), value.unsafeGet()); |
92 | EXPECT_EQ(std::numeric_limits<type>::max(), (value + std::numeric_limits<type>::max()).unsafeGet()); |
93 | EXPECT_EQ(std::numeric_limits<type>::max(), (std::numeric_limits<type>::max() + value).unsafeGet()); |
94 | EXPECT_EQ(std::numeric_limits<type>::min(), (value + std::numeric_limits<type>::min()).unsafeGet()); |
95 | EXPECT_EQ(std::numeric_limits<type>::min(), (std::numeric_limits<type>::min() + value).unsafeGet()); |
96 | |
97 | EXPECT_EQ(coerceLiteral(0), (value * coerceLiteral(0)).unsafeGet()); |
98 | EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) * value).unsafeGet()); |
99 | EXPECT_EQ(coerceLiteral(0), (value * value).unsafeGet()); |
100 | EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(0)).unsafeGet()); |
101 | EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) - value).unsafeGet()); |
102 | EXPECT_EQ(coerceLiteral(0), (value - value).unsafeGet()); |
103 | EXPECT_EQ(coerceLiteral(0), (value++).unsafeGet()); |
104 | EXPECT_EQ(coerceLiteral(1), (value--).unsafeGet()); |
105 | EXPECT_EQ(coerceLiteral(1), (++value).unsafeGet()); |
106 | EXPECT_EQ(coerceLiteral(0), (--value).unsafeGet()); |
107 | EXPECT_EQ(coerceLiteral(10), (value += coerceLiteral(10)).unsafeGet()); |
108 | EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); |
109 | EXPECT_EQ(coerceLiteral(100), (value *= coerceLiteral(10)).unsafeGet()); |
110 | EXPECT_EQ(coerceLiteral(100), value.unsafeGet()); |
111 | EXPECT_EQ(coerceLiteral(0), (value -= coerceLiteral(100)).unsafeGet()); |
112 | EXPECT_EQ(coerceLiteral(0), value.unsafeGet()); |
113 | value = 10; |
114 | EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); |
115 | EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(10)).unsafeGet()); |
116 | EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); |
117 | |
118 | value = std::numeric_limits<type>::min(); |
119 | EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - coerceLiteral(1))).hasOverflowed()); |
120 | EXPECT_EQ(true, !((value--).hasOverflowed())); |
121 | EXPECT_EQ(true, value.hasOverflowed()); |
122 | value = std::numeric_limits<type>::max(); |
123 | EXPECT_EQ(true, !value.hasOverflowed()); |
124 | EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + coerceLiteral(1))).hasOverflowed()); |
125 | EXPECT_EQ(true, !(value++).hasOverflowed()); |
126 | EXPECT_EQ(true, value.hasOverflowed()); |
127 | value = std::numeric_limits<type>::max(); |
128 | EXPECT_EQ(true, (value += coerceLiteral(1)).hasOverflowed()); |
129 | EXPECT_EQ(true, value.hasOverflowed()); |
130 | |
131 | value = 10; |
132 | type _value = 0; |
133 | EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(0)).safeGet(_value)); |
134 | _value = 0; |
135 | EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(0) * value).safeGet(_value)); |
136 | _value = 0; |
137 | EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); |
138 | _value = 0; |
139 | EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); |
140 | value = 0; |
141 | _value = 0; |
142 | EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); |
143 | _value = 0; |
144 | EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); |
145 | value = 1; |
146 | _value = 0; |
147 | EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); |
148 | _value = 0; |
149 | EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); |
150 | _value = 0; |
151 | value = 0; |
152 | EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); |
153 | _value = 0; |
154 | EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)0).safeGet(_value)); |
155 | _value = 0; |
156 | value = 1; |
157 | EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); |
158 | _value = 0; |
159 | EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)1).safeGet(_value)); |
160 | _value = 0; |
161 | value = 2; |
162 | EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); |
163 | _value = 0; |
164 | EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)2).safeGet(_value)); |
165 | value = 10; |
166 | EXPECT_EQ(true, (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).hasOverflowed()); |
167 | |
168 | |
169 | Checked<type, OverflowCrashLogger> nvalue; // to hold a not overflowed value. |
170 | Checked<type, OverflowCrashLogger> ovalue; // to hold an overflowed value. |
171 | |
172 | bool unused; |
173 | UNUSED_PARAM(unused); |
174 | |
175 | _value = 75; |
176 | type _largeValue = 100; |
177 | type _smallValue = 50; |
178 | |
179 | value = _smallValue; |
180 | nvalue = _value; |
181 | ovalue = _value; |
182 | |
183 | // Make sure the OverflowCrashLogger is working as expected. |
184 | EXPECT_EQ(false, (ovalue.hasOverflowed())); |
185 | EXPECT_EQ(true, (resetOverflow(ovalue), ovalue.hasOverflowed())); |
186 | EXPECT_EQ(false, (resetOverflow(ovalue), ovalue.didCrash())); |
187 | EXPECT_EQ(true, (unused = (ovalue == ovalue), ovalue.didCrash())); |
188 | EXPECT_EQ(false, (resetOverflow(ovalue), ovalue.didCrash())); |
189 | |
190 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
191 | EXPECT_EQ(false, nvalue.didCrash()); |
192 | |
193 | // Test operator== that should not overflow nor crash. |
194 | EXPECT_EQ(true, (nvalue == nvalue)); |
195 | EXPECT_EQ(true, (nvalue == Checked<type, OverflowCrashLogger>(_value))); |
196 | EXPECT_EQ(false, (nvalue == value)); |
197 | EXPECT_EQ(true, (nvalue == _value)); |
198 | EXPECT_EQ(false, (nvalue == Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max()))); |
199 | EXPECT_EQ(false, (nvalue == std::numeric_limits<type>::max())); |
200 | |
201 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
202 | EXPECT_EQ(false, nvalue.didCrash()); |
203 | |
204 | // Test operator!= that should not overflow nor crash. |
205 | EXPECT_EQ(false, (nvalue != nvalue)); |
206 | EXPECT_EQ(false, (nvalue != Checked<type, OverflowCrashLogger>(_value))); |
207 | EXPECT_EQ(true, (nvalue != value)); |
208 | EXPECT_EQ(false, (nvalue != _value)); |
209 | EXPECT_EQ(true, (nvalue != Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max()))); |
210 | EXPECT_EQ(true, (nvalue != std::numeric_limits<type>::max())); |
211 | |
212 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
213 | EXPECT_EQ(false, nvalue.didCrash()); |
214 | |
215 | // Test operator< that should not overflow nor crash. |
216 | EXPECT_EQ(false, (nvalue < nvalue)); |
217 | EXPECT_EQ(false, (nvalue < value)); |
218 | EXPECT_EQ(true, (nvalue < Checked<type, OverflowCrashLogger>(_largeValue))); |
219 | EXPECT_EQ(false, (nvalue < Checked<type, OverflowCrashLogger>(_value))); |
220 | EXPECT_EQ(false, (nvalue < Checked<type, OverflowCrashLogger>(_smallValue))); |
221 | EXPECT_EQ(true, (nvalue < _largeValue)); |
222 | EXPECT_EQ(false, (nvalue < _value)); |
223 | EXPECT_EQ(false, (nvalue < _smallValue)); |
224 | EXPECT_EQ(true, (nvalue < Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max()))); |
225 | EXPECT_EQ(true, (nvalue < std::numeric_limits<type>::max())); |
226 | |
227 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
228 | EXPECT_EQ(false, nvalue.didCrash()); |
229 | |
230 | // Test operator<= that should not overflow nor crash. |
231 | EXPECT_EQ(true, (nvalue <= nvalue)); |
232 | EXPECT_EQ(false, (nvalue <= value)); |
233 | EXPECT_EQ(true, (nvalue <= Checked<type, OverflowCrashLogger>(_largeValue))); |
234 | EXPECT_EQ(true, (nvalue <= Checked<type, OverflowCrashLogger>(_value))); |
235 | EXPECT_EQ(false, (nvalue <= Checked<type, OverflowCrashLogger>(_smallValue))); |
236 | EXPECT_EQ(true, (nvalue <= _largeValue)); |
237 | EXPECT_EQ(true, (nvalue <= _value)); |
238 | EXPECT_EQ(false, (nvalue <= _smallValue)); |
239 | EXPECT_EQ(true, (nvalue <= Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max()))); |
240 | EXPECT_EQ(true, (nvalue <= std::numeric_limits<type>::max())); |
241 | |
242 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
243 | EXPECT_EQ(false, nvalue.didCrash()); |
244 | |
245 | // Test operator> that should not overflow nor crash. |
246 | EXPECT_EQ(false, (nvalue > nvalue)); |
247 | EXPECT_EQ(true, (nvalue > value)); |
248 | EXPECT_EQ(false, (nvalue > Checked<type, OverflowCrashLogger>(_largeValue))); |
249 | EXPECT_EQ(false, (nvalue > Checked<type, OverflowCrashLogger>(_value))); |
250 | EXPECT_EQ(true, (nvalue > Checked<type, OverflowCrashLogger>(_smallValue))); |
251 | EXPECT_EQ(false, (nvalue > _largeValue)); |
252 | EXPECT_EQ(false, (nvalue > _value)); |
253 | EXPECT_EQ(true, (nvalue > _smallValue)); |
254 | EXPECT_EQ(false, (nvalue > Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max()))); |
255 | EXPECT_EQ(false, (nvalue > std::numeric_limits<type>::max())); |
256 | |
257 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
258 | EXPECT_EQ(false, nvalue.didCrash()); |
259 | |
260 | // Test operator>= that should not overflow nor crash. |
261 | EXPECT_EQ(true, (nvalue >= nvalue)); |
262 | EXPECT_EQ(true, (nvalue >= value)); |
263 | EXPECT_EQ(false, (nvalue >= Checked<type, OverflowCrashLogger>(_largeValue))); |
264 | EXPECT_EQ(true, (nvalue >= Checked<type, OverflowCrashLogger>(_value))); |
265 | EXPECT_EQ(true, (nvalue >= Checked<type, OverflowCrashLogger>(_smallValue))); |
266 | EXPECT_EQ(false, (nvalue >= _largeValue)); |
267 | EXPECT_EQ(true, (nvalue >= _value)); |
268 | EXPECT_EQ(true, (nvalue >= _smallValue)); |
269 | EXPECT_EQ(false, (nvalue >= Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max()))); |
270 | EXPECT_EQ(false, (nvalue >= std::numeric_limits<type>::max())); |
271 | |
272 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
273 | EXPECT_EQ(false, nvalue.didCrash()); |
274 | |
275 | // Test operator== with an overflowed value. |
276 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == ovalue), ovalue.didCrash())); |
277 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash())); |
278 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == value), ovalue.didCrash())); |
279 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == _value), ovalue.didCrash())); |
280 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == _value * std::numeric_limits<type>::max()), ovalue.didCrash())); |
281 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash())); |
282 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == std::numeric_limits<type>::max()), ovalue.didCrash())); |
283 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == nvalue), ovalue.didCrash())); |
284 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue == ovalue), ovalue.didCrash())); |
285 | |
286 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
287 | |
288 | // Test operator!= with an overflowed value. |
289 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != ovalue), ovalue.didCrash())); |
290 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash())); |
291 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != value), ovalue.didCrash())); |
292 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != _value), ovalue.didCrash())); |
293 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != _value * std::numeric_limits<type>::max()), ovalue.didCrash())); |
294 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash())); |
295 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != std::numeric_limits<type>::max()), ovalue.didCrash())); |
296 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != nvalue), ovalue.didCrash())); |
297 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue != ovalue), ovalue.didCrash())); |
298 | |
299 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
300 | |
301 | // Test operator< with an overflowed value. |
302 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < ovalue), ovalue.didCrash())); |
303 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < value), ovalue.didCrash())); |
304 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked<type, OverflowCrashLogger>(_largeValue)), ovalue.didCrash())); |
305 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash())); |
306 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked<type, OverflowCrashLogger>(_smallValue)), ovalue.didCrash())); |
307 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < _largeValue), ovalue.didCrash())); |
308 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < _value), ovalue.didCrash())); |
309 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < _smallValue), ovalue.didCrash())); |
310 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash())); |
311 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < std::numeric_limits<type>::max()), ovalue.didCrash())); |
312 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < nvalue), ovalue.didCrash())); |
313 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue < ovalue), ovalue.didCrash())); |
314 | |
315 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
316 | |
317 | // Test operator<= with an overflowed value. |
318 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= ovalue), ovalue.didCrash())); |
319 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= value), ovalue.didCrash())); |
320 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked<type, OverflowCrashLogger>(_largeValue)), ovalue.didCrash())); |
321 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash())); |
322 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked<type, OverflowCrashLogger>(_smallValue)), ovalue.didCrash())); |
323 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= _largeValue), ovalue.didCrash())); |
324 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= _value), ovalue.didCrash())); |
325 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= _smallValue), ovalue.didCrash())); |
326 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash())); |
327 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= std::numeric_limits<type>::max()), ovalue.didCrash())); |
328 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= nvalue), ovalue.didCrash())); |
329 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue <= ovalue), ovalue.didCrash())); |
330 | |
331 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
332 | |
333 | // Test operator> with an overflowed value. |
334 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > ovalue), ovalue.didCrash())); |
335 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > value), ovalue.didCrash())); |
336 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked<type, OverflowCrashLogger>(_largeValue)), ovalue.didCrash())); |
337 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash())); |
338 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked<type, OverflowCrashLogger>(_smallValue)), ovalue.didCrash())); |
339 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > _largeValue), ovalue.didCrash())); |
340 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > _value), ovalue.didCrash())); |
341 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > _smallValue), ovalue.didCrash())); |
342 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash())); |
343 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > std::numeric_limits<type>::max()), ovalue.didCrash())); |
344 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > nvalue), ovalue.didCrash())); |
345 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue > ovalue), ovalue.didCrash())); |
346 | |
347 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
348 | |
349 | // Test operator>= with an overflowed value. |
350 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= ovalue), ovalue.didCrash())); |
351 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= value), ovalue.didCrash())); |
352 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked<type, OverflowCrashLogger>(_largeValue)), ovalue.didCrash())); |
353 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash())); |
354 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked<type, OverflowCrashLogger>(_smallValue)), ovalue.didCrash())); |
355 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= _largeValue), ovalue.didCrash())); |
356 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= _value), ovalue.didCrash())); |
357 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= _smallValue), ovalue.didCrash())); |
358 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash())); |
359 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= std::numeric_limits<type>::max()), ovalue.didCrash())); |
360 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= nvalue), ovalue.didCrash())); |
361 | EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue >= ovalue), ovalue.didCrash())); |
362 | |
363 | EXPECT_EQ(false, nvalue.hasOverflowed()); |
364 | |
365 | MixedSignednessTester::run(); |
366 | } |
367 | }; |
368 | |
369 | template <typename type, typename Coercer> |
370 | class AllowMixedSignednessTest { |
371 | public: |
372 | static void run() |
373 | { |
374 | Checked<type, RecordOverflow> value; |
375 | value = 10; |
376 | |
377 | EXPECT_EQ(coerceLiteral(0), (value + -10).unsafeGet()); |
378 | EXPECT_EQ(0U, (value - 10U).unsafeGet()); |
379 | EXPECT_EQ(coerceLiteral(0), (-10 + value).unsafeGet()); |
380 | EXPECT_EQ(0U, (10U - value).unsafeGet()); |
381 | value = std::numeric_limits<type>::min(); |
382 | EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - 1)).hasOverflowed()); |
383 | EXPECT_EQ(true, !(value--).hasOverflowed()); |
384 | EXPECT_EQ(true, value.hasOverflowed()); |
385 | value = std::numeric_limits<type>::max(); |
386 | EXPECT_EQ(true, !value.hasOverflowed()); |
387 | EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1)).hasOverflowed()); |
388 | EXPECT_EQ(true, !(value++).hasOverflowed()); |
389 | EXPECT_EQ(true, value.hasOverflowed()); |
390 | value = std::numeric_limits<type>::max(); |
391 | EXPECT_EQ(true, (value += 1).hasOverflowed()); |
392 | EXPECT_EQ(true, value.hasOverflowed()); |
393 | value = std::numeric_limits<type>::min(); |
394 | EXPECT_EQ(true, (value - 1U).hasOverflowed()); |
395 | EXPECT_EQ(true, !(value--).hasOverflowed()); |
396 | EXPECT_EQ(true, value.hasOverflowed()); |
397 | value = std::numeric_limits<type>::max(); |
398 | EXPECT_EQ(true, !value.hasOverflowed()); |
399 | EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1U)).hasOverflowed()); |
400 | EXPECT_EQ(true, !(value++).hasOverflowed()); |
401 | EXPECT_EQ(true, value.hasOverflowed()); |
402 | value = std::numeric_limits<type>::max(); |
403 | EXPECT_EQ(true, (value += 1U).hasOverflowed()); |
404 | EXPECT_EQ(true, value.hasOverflowed()); |
405 | } |
406 | }; |
407 | |
408 | template <typename type, typename Coercer> |
409 | class IgnoreMixedSignednessTest { |
410 | public: |
411 | static void run() { } |
412 | }; |
413 | |
414 | template <typename type> class CoerceLiteralToUnsigned { |
415 | public: |
416 | static unsigned coerce(type x) { return static_cast<unsigned>(x); } |
417 | }; |
418 | |
419 | template <typename type> class CoerceLiteralNop { |
420 | public: |
421 | static type coerce(type x) { return x; } |
422 | }; |
423 | |
424 | CheckedArithmeticTest(int8_t, CoerceLiteralNop, IgnoreMixedSignednessTest) |
425 | CheckedArithmeticTest(int16_t, CoerceLiteralNop, IgnoreMixedSignednessTest) |
426 | CheckedArithmeticTest(int32_t, CoerceLiteralNop, AllowMixedSignednessTest) |
427 | CheckedArithmeticTest(uint32_t, CoerceLiteralToUnsigned, AllowMixedSignednessTest) |
428 | CheckedArithmeticTest(int64_t, CoerceLiteralNop, IgnoreMixedSignednessTest) |
429 | CheckedArithmeticTest(uint64_t, CoerceLiteralToUnsigned, IgnoreMixedSignednessTest) |
430 | |
431 | TEST(CheckedArithmeticTest, IsInBounds) |
432 | { |
433 | // bigger precision, signed, signed |
434 | EXPECT_TRUE(WTF::isInBounds<int32_t>(std::numeric_limits<int16_t>::max())); |
435 | EXPECT_TRUE(WTF::isInBounds<int32_t>(std::numeric_limits<int16_t>::min())); |
436 | |
437 | // bigger precision, unsigned, signed |
438 | EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<int32_t>::max())); |
439 | EXPECT_FALSE(WTF::isInBounds<uint32_t>(std::numeric_limits<int16_t>::min())); |
440 | |
441 | EXPECT_FALSE(WTF::isInBounds<uint32_t>((int32_t)-1)); |
442 | EXPECT_FALSE(WTF::isInBounds<uint16_t>((int32_t)-1)); |
443 | EXPECT_FALSE(WTF::isInBounds<unsigned long>((int)-1)); |
444 | |
445 | EXPECT_TRUE(WTF::isInBounds<uint32_t>((int32_t)1)); |
446 | EXPECT_TRUE(WTF::isInBounds<uint32_t>((int16_t)1)); |
447 | EXPECT_TRUE(WTF::isInBounds<unsigned>((int)1)); |
448 | |
449 | EXPECT_TRUE(WTF::isInBounds<uint32_t>((int32_t)0)); |
450 | EXPECT_TRUE(WTF::isInBounds<uint16_t>((int32_t)0)); |
451 | EXPECT_TRUE(WTF::isInBounds<uint32_t>((int16_t)0)); |
452 | EXPECT_TRUE(WTF::isInBounds<unsigned>((int)0)); |
453 | |
454 | EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<int32_t>::max())); |
455 | EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<int16_t>::max())); |
456 | EXPECT_TRUE(WTF::isInBounds<unsigned>(std::numeric_limits<int>::max())); |
457 | |
458 | // bigger precision, signed, unsigned |
459 | EXPECT_TRUE(WTF::isInBounds<int32_t>(std::numeric_limits<uint16_t>::max())); |
460 | EXPECT_FALSE(WTF::isInBounds<int32_t>(std::numeric_limits<uint32_t>::max())); |
461 | EXPECT_TRUE(WTF::isInBounds<int32_t>((uint32_t)0)); |
462 | |
463 | // bigger precision, unsigned, unsigned |
464 | EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<uint16_t>::max())); |
465 | EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<uint16_t>::min())); |
466 | |
467 | // lower precision, signed signed |
468 | EXPECT_FALSE(WTF::isInBounds<int16_t>(std::numeric_limits<int32_t>::max())); |
469 | EXPECT_FALSE(WTF::isInBounds<int16_t>(std::numeric_limits<int32_t>::min())); |
470 | EXPECT_TRUE(WTF::isInBounds<int16_t>((int32_t)-1)); |
471 | EXPECT_TRUE(WTF::isInBounds<int16_t>((int32_t)0)); |
472 | EXPECT_TRUE(WTF::isInBounds<int16_t>((int32_t)1)); |
473 | // lower precision, unsigned, signed |
474 | EXPECT_FALSE(WTF::isInBounds<uint16_t>(std::numeric_limits<int32_t>::max())); |
475 | EXPECT_FALSE(WTF::isInBounds<uint16_t>(std::numeric_limits<int32_t>::min())); |
476 | EXPECT_FALSE(WTF::isInBounds<uint16_t>((int32_t)-1)); |
477 | EXPECT_TRUE(WTF::isInBounds<uint16_t>((int32_t)0)); |
478 | EXPECT_TRUE(WTF::isInBounds<uint16_t>((int32_t)1)); |
479 | // lower precision, signed, unsigned |
480 | EXPECT_FALSE(WTF::isInBounds<int16_t>(std::numeric_limits<uint32_t>::max())); |
481 | EXPECT_TRUE(WTF::isInBounds<int16_t>((uint32_t)0)); |
482 | EXPECT_TRUE(WTF::isInBounds<int16_t>((uint32_t)1)); |
483 | // lower precision, unsigned, unsigned |
484 | EXPECT_FALSE(WTF::isInBounds<uint16_t>(std::numeric_limits<uint32_t>::max())); |
485 | EXPECT_TRUE(WTF::isInBounds<uint16_t>((uint32_t)0)); |
486 | EXPECT_TRUE(WTF::isInBounds<uint16_t>((uint32_t)1)); |
487 | } |
488 | |
489 | } // namespace TestWebKitAPI |
490 | |