1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6 #include <stdint.h>
7
8 #include <limits>
9 #include <type_traits>
10
11 #include "base/compiler_specific.h"
12 #include "base/numerics/safe_conversions.h"
13 #include "base/numerics/safe_math.h"
14 #include "build/build_config.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 #if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
18 #include <mmintrin.h>
19 #endif
20
21 using std::numeric_limits;
22 using base::CheckedNumeric;
23 using base::checked_cast;
24 using base::IsValueInRangeForNumericType;
25 using base::IsValueNegative;
26 using base::SizeT;
27 using base::StrictNumeric;
28 using base::saturated_cast;
29 using base::strict_cast;
30 using base::internal::MaxExponent;
31 using base::internal::RANGE_VALID;
32 using base::internal::RANGE_INVALID;
33 using base::internal::RANGE_OVERFLOW;
34 using base::internal::RANGE_UNDERFLOW;
35 using base::internal::SignedIntegerForSize;
36
37 // These tests deliberately cause arithmetic overflows. If the compiler is
38 // aggressive enough, it can const fold these overflows. Disable warnings about
39 // overflows for const expressions.
40 #if defined(OS_WIN)
41 #pragma warning(disable : 4756)
42 #endif
43
44 // This is a helper function for finding the maximum value in Src that can be
45 // wholy represented as the destination floating-point type.
46 template <typename Dst, typename Src>
GetMaxConvertibleToFloat()47 Dst GetMaxConvertibleToFloat()
48 {
49 typedef numeric_limits<Dst> DstLimits;
50 typedef numeric_limits<Src> SrcLimits;
51 static_assert(SrcLimits::is_specialized, "Source must be numeric.");
52 static_assert(DstLimits::is_specialized, "Destination must be numeric.");
53 CHECK(DstLimits::is_iec559);
54
55 if (SrcLimits::digits <= DstLimits::digits &&
56 MaxExponent<Src>::value <= MaxExponent<Dst>::value)
57 return SrcLimits::max();
58 Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
59 while (max != static_cast<Src>(static_cast<Dst>(max)))
60 {
61 max /= 2;
62 }
63 return static_cast<Dst>(max);
64 }
65
66 // Helper macros to wrap displaying the conversion types and line numbers.
67 #define TEST_EXPECTED_VALIDITY(expected, actual) \
68 EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).IsValid()) \
69 << "Result test: Value " << +(actual).ValueUnsafe() << " as " << dst << " on line " \
70 << line;
71
72 #define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
73 #define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
74
75 #define TEST_EXPECTED_VALUE(expected, actual) \
76 EXPECT_EQ(static_cast<Dst>(expected), CheckedNumeric<Dst>(actual).ValueUnsafe()) \
77 << "Result test: Value " << +((actual).ValueUnsafe()) << " as " << dst << " on line " \
78 << line;
79
80 // Signed integer arithmetic.
81 template <typename Dst>
TestSpecializedArithmetic(const char * dst,int line,typename std::enable_if<numeric_limits<Dst>::is_integer && numeric_limits<Dst>::is_signed,int>::type=0)82 static void TestSpecializedArithmetic(
83 const char *dst,
84 int line,
85 typename std::enable_if<numeric_limits<Dst>::is_integer && numeric_limits<Dst>::is_signed,
86 int>::type = 0)
87 {
88 typedef numeric_limits<Dst> DstLimits;
89 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::min()));
90 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()).Abs());
91 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
92
93 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
94 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) + -1);
95 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
96
97 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) - 1);
98 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) - -1);
99 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
100 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
101
102 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) * 2);
103
104 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) / -1);
105 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
106
107 // Modulus is legal only for integers.
108 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
109 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
110 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
111 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-1) % -2);
112 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
113 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
114 // Test all the different modulus combinations.
115 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
116 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
117 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
118 CheckedNumeric<Dst> checked_dst = 1;
119 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
120 }
121
122 // Unsigned integer arithmetic.
123 template <typename Dst>
TestSpecializedArithmetic(const char * dst,int line,typename std::enable_if<numeric_limits<Dst>::is_integer &&!numeric_limits<Dst>::is_signed,int>::type=0)124 static void TestSpecializedArithmetic(
125 const char *dst,
126 int line,
127 typename std::enable_if<numeric_limits<Dst>::is_integer && !numeric_limits<Dst>::is_signed,
128 int>::type = 0)
129 {
130 typedef numeric_limits<Dst> DstLimits;
131 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min()));
132 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs());
133 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) + -1);
134 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) - 1);
135 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) * 2);
136 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
137 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).UnsignedAbs());
138 TEST_EXPECTED_SUCCESS(CheckedNumeric<typename SignedIntegerForSize<Dst>::type>(
139 std::numeric_limits<typename SignedIntegerForSize<Dst>::type>::min())
140 .UnsignedAbs());
141
142 // Modulus is legal only for integers.
143 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
144 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
145 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
146 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
147 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
148 // Test all the different modulus combinations.
149 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
150 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
151 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
152 CheckedNumeric<Dst> checked_dst = 1;
153 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
154 }
155
156 // Floating point arithmetic.
157 template <typename Dst>
TestSpecializedArithmetic(const char * dst,int line,typename std::enable_if<numeric_limits<Dst>::is_iec559,int>::type=0)158 void TestSpecializedArithmetic(
159 const char *dst,
160 int line,
161 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0)
162 {
163 typedef numeric_limits<Dst> DstLimits;
164 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min()));
165
166 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs());
167 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
168
169 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + -1);
170 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
171 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
172
173 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
174 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
175
176 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2);
177
178 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
179 EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating());
180 }
181
182 // Generic arithmetic tests.
183 template <typename Dst>
TestArithmetic(const char * dst,int line)184 static void TestArithmetic(const char *dst, int line)
185 {
186 typedef numeric_limits<Dst> DstLimits;
187
188 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
189 EXPECT_EQ(
190 false,
191 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max()).IsValid());
192 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
193 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
194 EXPECT_EQ(static_cast<Dst>(1),
195 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max())
196 .ValueOrDefault(1));
197
198 // Test the operator combinations.
199 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
200 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
201 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
202 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
203 TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
204 TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
205 TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
206 TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
207 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
208 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
209 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
210 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
211 CheckedNumeric<Dst> checked_dst = 1;
212 TEST_EXPECTED_VALUE(2, checked_dst += 1);
213 checked_dst = 1;
214 TEST_EXPECTED_VALUE(0, checked_dst -= 1);
215 checked_dst = 1;
216 TEST_EXPECTED_VALUE(1, checked_dst *= 1);
217 checked_dst = 1;
218 TEST_EXPECTED_VALUE(1, checked_dst /= 1);
219
220 // Generic negation.
221 TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
222 TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
223 TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
224 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
225 -CheckedNumeric<Dst>(DstLimits::max()));
226
227 // Generic absolute value.
228 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
229 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
230 TEST_EXPECTED_VALUE(DstLimits::max(), CheckedNumeric<Dst>(DstLimits::max()).Abs());
231
232 // Generic addition.
233 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
234 TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
235 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
236 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + 1);
237 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
238
239 // Generic subtraction.
240 TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
241 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
242 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
243 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
244
245 // Generic multiplication.
246 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
247 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
248 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
249 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
250 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
251 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
252 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
253
254 // Generic division.
255 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
256 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
257 TEST_EXPECTED_VALUE(DstLimits::min() / 2, CheckedNumeric<Dst>(DstLimits::min()) / 2);
258 TEST_EXPECTED_VALUE(DstLimits::max() / 2, CheckedNumeric<Dst>(DstLimits::max()) / 2);
259
260 TestSpecializedArithmetic<Dst>(dst, line);
261 }
262
263 // Helper macro to wrap displaying the conversion types and line numbers.
264 #define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
265
TEST(SafeNumerics,SignedIntegerMath)266 TEST(SafeNumerics, SignedIntegerMath)
267 {
268 TEST_ARITHMETIC(int8_t);
269 TEST_ARITHMETIC(int);
270 TEST_ARITHMETIC(intptr_t);
271 TEST_ARITHMETIC(intmax_t);
272 }
273
TEST(SafeNumerics,UnsignedIntegerMath)274 TEST(SafeNumerics, UnsignedIntegerMath)
275 {
276 TEST_ARITHMETIC(uint8_t);
277 TEST_ARITHMETIC(unsigned int);
278 TEST_ARITHMETIC(uintptr_t);
279 TEST_ARITHMETIC(uintmax_t);
280 }
281
TEST(SafeNumerics,FloatingPointMath)282 TEST(SafeNumerics, FloatingPointMath)
283 {
284 TEST_ARITHMETIC(float);
285 TEST_ARITHMETIC(double);
286 }
287
288 // Enumerates the five different conversions types we need to test.
289 enum NumericConversionType
290 {
291 SIGN_PRESERVING_VALUE_PRESERVING,
292 SIGN_PRESERVING_NARROW,
293 SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
294 SIGN_TO_UNSIGN_NARROW,
295 UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
296 };
297
298 // Template covering the different conversion tests.
299 template <typename Dst, typename Src, NumericConversionType conversion>
300 struct TestNumericConversion
301 {
302 };
303
304 // EXPECT_EQ wrappers providing specific detail on test failures.
305 #define TEST_EXPECTED_RANGE(expected, actual) \
306 EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \
307 << "Conversion test: " << src << " value " << actual << " to " << dst << " on line " \
308 << line;
309
310 template <typename Dst, typename Src>
311 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING>
312 {
TestTestNumericConversion313 static void Test(const char *dst, const char *src, int line)
314 {
315 typedef numeric_limits<Src> SrcLimits;
316 typedef numeric_limits<Dst> DstLimits;
317 // Integral to floating.
318 static_assert(
319 (DstLimits::is_iec559 && SrcLimits::is_integer) ||
320 // Not floating to integral and...
321 (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
322 // Same sign, same numeric, source is narrower or same.
323 ((SrcLimits::is_signed == DstLimits::is_signed && sizeof(Dst) >= sizeof(Src)) ||
324 // Or signed destination and source is smaller
325 (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))),
326 "Comparison must be sign preserving and value preserving");
327
328 const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
329 TEST_EXPECTED_SUCCESS(checked_dst);
330 if (MaxExponent<Dst>::value > MaxExponent<Src>::value)
331 {
332 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1)
333 {
334 // At least twice larger type.
335 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
336 }
337 else
338 { // Larger, but not at least twice as large.
339 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
340 TEST_EXPECTED_SUCCESS(checked_dst + 1);
341 }
342 }
343 else
344 { // Same width type.
345 TEST_EXPECTED_FAILURE(checked_dst + 1);
346 }
347
348 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
349 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
350 if (SrcLimits::is_iec559)
351 {
352 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
353 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
354 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
355 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
356 }
357 else if (numeric_limits<Src>::is_signed)
358 {
359 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
360 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
361 }
362 }
363 };
364
365 template <typename Dst, typename Src>
366 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW>
367 {
TestTestNumericConversion368 static void Test(const char *dst, const char *src, int line)
369 {
370 typedef numeric_limits<Src> SrcLimits;
371 typedef numeric_limits<Dst> DstLimits;
372 static_assert(SrcLimits::is_signed == DstLimits::is_signed,
373 "Destination and source sign must be the same");
374 static_assert(sizeof(Dst) < sizeof(Src) || (DstLimits::is_integer && SrcLimits::is_iec559),
375 "Destination must be narrower than source");
376
377 const CheckedNumeric<Dst> checked_dst;
378 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
379 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
380 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
381
382 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
383 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
384 if (SrcLimits::is_iec559)
385 {
386 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
387 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
388 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
389 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
390 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
391 if (DstLimits::is_integer)
392 {
393 if (SrcLimits::digits < DstLimits::digits)
394 {
395 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, static_cast<Src>(DstLimits::max()));
396 }
397 else
398 {
399 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
400 }
401 TEST_EXPECTED_RANGE(RANGE_VALID,
402 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
403 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
404 }
405 }
406 else if (SrcLimits::is_signed)
407 {
408 TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
409 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
410 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
411 }
412 else
413 {
414 TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
415 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
416 }
417 }
418 };
419
420 template <typename Dst, typename Src>
421 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL>
422 {
TestTestNumericConversion423 static void Test(const char *dst, const char *src, int line)
424 {
425 typedef numeric_limits<Src> SrcLimits;
426 typedef numeric_limits<Dst> DstLimits;
427 static_assert(sizeof(Dst) >= sizeof(Src),
428 "Destination must be equal or wider than source.");
429 static_assert(SrcLimits::is_signed, "Source must be signed");
430 static_assert(!DstLimits::is_signed, "Destination must be unsigned");
431
432 const CheckedNumeric<Dst> checked_dst;
433 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
434 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
435 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max());
436
437 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
438 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
439 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
440 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
441 }
442 };
443
444 template <typename Dst, typename Src>
445 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW>
446 {
TestTestNumericConversion447 static void Test(const char *dst, const char *src, int line)
448 {
449 typedef numeric_limits<Src> SrcLimits;
450 typedef numeric_limits<Dst> DstLimits;
451 static_assert(
452 (DstLimits::is_integer && SrcLimits::is_iec559) || (sizeof(Dst) < sizeof(Src)),
453 "Destination must be narrower than source.");
454 static_assert(SrcLimits::is_signed, "Source must be signed.");
455 static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
456
457 const CheckedNumeric<Dst> checked_dst;
458 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
459 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
460 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
461 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max());
462
463 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
464 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
465 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
466 if (SrcLimits::is_iec559)
467 {
468 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
469 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
470 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
471 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
472 if (DstLimits::is_integer)
473 {
474 if (SrcLimits::digits < DstLimits::digits)
475 {
476 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, static_cast<Src>(DstLimits::max()));
477 }
478 else
479 {
480 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
481 }
482 TEST_EXPECTED_RANGE(RANGE_VALID,
483 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
484 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
485 }
486 }
487 else
488 {
489 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
490 }
491 }
492 };
493
494 template <typename Dst, typename Src>
495 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL>
496 {
TestTestNumericConversion497 static void Test(const char *dst, const char *src, int line)
498 {
499 typedef numeric_limits<Src> SrcLimits;
500 typedef numeric_limits<Dst> DstLimits;
501 static_assert(sizeof(Dst) <= sizeof(Src),
502 "Destination must be narrower or equal to source.");
503 static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
504 static_assert(DstLimits::is_signed, "Destination must be signed.");
505
506 const CheckedNumeric<Dst> checked_dst;
507 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
508 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
509 TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min());
510
511 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
512 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
513 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
514 }
515 };
516
517 // Helper macro to wrap displaying the conversion types and line numbers
518 #define TEST_NUMERIC_CONVERSION(d, s, t) TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
519
TEST(SafeNumerics,IntMinOperations)520 TEST(SafeNumerics, IntMinOperations)
521 {
522 TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
523 TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
524
525 TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
526 TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
527 TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
528
529 TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
530
531 TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
532 TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
533 TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
534
535 TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
536 TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
537 }
538
TEST(SafeNumerics,IntOperations)539 TEST(SafeNumerics, IntOperations)
540 {
541 TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
542 TEST_NUMERIC_CONVERSION(unsigned int, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
543 TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
544 TEST_NUMERIC_CONVERSION(unsigned int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
545 TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
546
547 TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
548 TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
549 TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
550 TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
551
552 TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
553 TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
554
555 TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
556 TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
557 TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
558
559 TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
560 TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
561 }
562
TEST(SafeNumerics,IntMaxOperations)563 TEST(SafeNumerics, IntMaxOperations)
564 {
565 TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
566 TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
567 TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
568 TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
569 TEST_NUMERIC_CONVERSION(intmax_t, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
570 TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
571
572 TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
573 TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
574
575 TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
576 TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
577
578 TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
579 TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
580
581 TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
582 }
583
TEST(SafeNumerics,FloatOperations)584 TEST(SafeNumerics, FloatOperations)
585 {
586 TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
587 TEST_NUMERIC_CONVERSION(float, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
588 TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
589 TEST_NUMERIC_CONVERSION(float, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
590
591 TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
592 }
593
TEST(SafeNumerics,DoubleOperations)594 TEST(SafeNumerics, DoubleOperations)
595 {
596 TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
597 TEST_NUMERIC_CONVERSION(double, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
598 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
599 TEST_NUMERIC_CONVERSION(double, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
600 }
601
TEST(SafeNumerics,SizeTOperations)602 TEST(SafeNumerics, SizeTOperations)
603 {
604 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
605 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
606 }
607
TEST(SafeNumerics,CastTests)608 TEST(SafeNumerics, CastTests)
609 {
610 // MSVC catches and warns that we're forcing saturation in these tests.
611 // Since that's intentional, we need to shut this warning off.
612 #if defined(COMPILER_MSVC)
613 #pragma warning(disable : 4756)
614 #endif
615
616 int small_positive = 1;
617 int small_negative = -1;
618 double double_small = 1.0;
619 double double_large = numeric_limits<double>::max();
620 double double_infinity = numeric_limits<float>::infinity();
621 double double_large_int = numeric_limits<int>::max();
622 double double_small_int = numeric_limits<int>::min();
623
624 // Just test that the casts compile, since the other tests cover logic.
625 EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
626 EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
627 EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
628 EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
629 EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
630 EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
631 EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
632
633 EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
634 EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
635 EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
636
637 EXPECT_TRUE(IsValueNegative(-1));
638 EXPECT_TRUE(IsValueNegative(numeric_limits<int>::min()));
639 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::min()));
640 EXPECT_TRUE(IsValueNegative(-numeric_limits<double>::max()));
641 EXPECT_FALSE(IsValueNegative(0));
642 EXPECT_FALSE(IsValueNegative(1));
643 EXPECT_FALSE(IsValueNegative(0u));
644 EXPECT_FALSE(IsValueNegative(1u));
645 EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
646 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
647 EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
648
649 // These casts and coercions will fail to compile:
650 // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0)));
651 // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0)));
652 // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1));
653 // EXPECT_EQ(1, StrictNumeric<size_t>(1U));
654
655 // Test various saturation corner cases.
656 EXPECT_EQ(saturated_cast<int>(small_negative), static_cast<int>(small_negative));
657 EXPECT_EQ(saturated_cast<int>(small_positive), static_cast<int>(small_positive));
658 EXPECT_EQ(saturated_cast<unsigned>(small_negative), static_cast<unsigned>(0));
659 EXPECT_EQ(saturated_cast<int>(double_small), static_cast<int>(double_small));
660 EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
661 EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
662 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
663 EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int));
664 EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
665
666 float not_a_number =
667 std::numeric_limits<float>::infinity() - std::numeric_limits<float>::infinity();
668 EXPECT_TRUE(std::isnan(not_a_number));
669 EXPECT_EQ(0, saturated_cast<int>(not_a_number));
670 }
671
672 #if GTEST_HAS_DEATH_TEST
673
TEST(SafeNumerics,SaturatedCastChecks)674 TEST(SafeNumerics, SaturatedCastChecks)
675 {
676 float not_a_number =
677 std::numeric_limits<float>::infinity() - std::numeric_limits<float>::infinity();
678 EXPECT_TRUE(std::isnan(not_a_number));
679 EXPECT_DEATH((saturated_cast<int, base::SaturatedCastNaNBehaviorCheck>(not_a_number)), "");
680 }
681
682 #endif // GTEST_HAS_DEATH_TEST
683
TEST(SafeNumerics,IsValueInRangeForNumericType)684 TEST(SafeNumerics, IsValueInRangeForNumericType)
685 {
686 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
687 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
688 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
689 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
690 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
691 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
692 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
693 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
694 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(std::numeric_limits<int32_t>::min()));
695 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(std::numeric_limits<int64_t>::min()));
696
697 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
698 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
699 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
700 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
701 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
702 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
703 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
704 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
705 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
706 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
707 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
708 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(std::numeric_limits<int32_t>::min()));
709 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
710 static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
711 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
712 static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1));
713 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(std::numeric_limits<int64_t>::min()));
714
715 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
716 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
717 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
718 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
719 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
720 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
721 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
722 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
723 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(std::numeric_limits<int32_t>::min()));
724 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
725 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(std::numeric_limits<int64_t>::min()));
726
727 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
728 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
729 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
730 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
731 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
732 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
733 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
734 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
735 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
736 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
737 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
738 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
739 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
740 EXPECT_FALSE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
741 EXPECT_FALSE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
742 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(std::numeric_limits<int32_t>::min()));
743 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
744 static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
745 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(std::numeric_limits<int64_t>::min()));
746 }
747
TEST(SafeNumerics,CompoundNumericOperations)748 TEST(SafeNumerics, CompoundNumericOperations)
749 {
750 CheckedNumeric<int> a = 1;
751 CheckedNumeric<int> b = 2;
752 CheckedNumeric<int> c = 3;
753 CheckedNumeric<int> d = 4;
754 a += b;
755 EXPECT_EQ(3, a.ValueOrDie());
756 a -= c;
757 EXPECT_EQ(0, a.ValueOrDie());
758 d /= b;
759 EXPECT_EQ(2, d.ValueOrDie());
760 d *= d;
761 EXPECT_EQ(4, d.ValueOrDie());
762
763 CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
764 EXPECT_TRUE(too_large.IsValid());
765 too_large += d;
766 EXPECT_FALSE(too_large.IsValid());
767 too_large -= d;
768 EXPECT_FALSE(too_large.IsValid());
769 too_large /= d;
770 EXPECT_FALSE(too_large.IsValid());
771 }
772