Use constexpr instead of const in symbol definitions that are obviously constexpr.
[WebKit-https.git] / Source / WTF / wtf / CheckedArithmetic.h
1 /*
2  * Copyright (C) 2011-2019 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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #pragma once
27
28 #include <wtf/Assertions.h>
29
30 #include <limits>
31 #include <stdint.h>
32 #include <type_traits>
33
34 /* Checked<T>
35  *
36  * This class provides a mechanism to perform overflow-safe integer arithmetic
37  * without having to manually ensure that you have all the required bounds checks
38  * directly in your code.
39  *
40  * There are two modes of operation:
41  *  - The default is Checked<T, CrashOnOverflow>, and crashes at the point
42  *    and overflow has occurred.
43  *  - The alternative is Checked<T, RecordOverflow>, which uses an additional
44  *    byte of storage to track whether an overflow has occurred, subsequent
45  *    unchecked operations will crash if an overflow has occured
46  *
47  * It is possible to provide a custom overflow handler, in which case you need
48  * to support these functions:
49  *  - void overflowed();
50  *    This function is called when an operation has produced an overflow.
51  *  - bool hasOverflowed();
52  *    This function must return true if overflowed() has been called on an
53  *    instance and false if it has not.
54  *  - void clearOverflow();
55  *    Used to reset overflow tracking when a value is being overwritten with
56  *    a new value.
57  *
58  * Checked<T> works for all integer types, with the following caveats:
59  *  - Mixing signedness of operands is only supported for types narrower than
60  *    64bits.
61  *  - It does have a performance impact, so tight loops may want to be careful
62  *    when using it.
63  *
64  */
65
66 namespace WTF {
67
68 enum class CheckedState {
69     DidOverflow,
70     DidNotOverflow
71 };
72
73 class AssertNoOverflow {
74 public:
75     static NO_RETURN_DUE_TO_ASSERT void overflowed()
76     {
77         ASSERT_NOT_REACHED();
78     }
79
80     void clearOverflow() { }
81
82     static NO_RETURN_DUE_TO_CRASH void crash()
83     {
84         CRASH();
85     }
86
87 public:
88     constexpr bool hasOverflowed() const { return false; }
89 };
90
91 class ConditionalCrashOnOverflow {
92 public:
93     void overflowed()
94     {
95         m_overflowed = true;
96         if (m_shouldCrashOnOverflow)
97             crash();
98     }
99
100     bool shouldCrashOnOverflow() const { return m_shouldCrashOnOverflow; }
101     void setShouldCrashOnOverflow(bool value) { m_shouldCrashOnOverflow = value; }
102
103     bool hasOverflowed() const { return m_overflowed; }
104     void clearOverflow() { m_overflowed = false; }
105
106     static NO_RETURN_DUE_TO_CRASH void crash()
107     {
108         CRASH();
109     }
110
111 private:
112     bool m_overflowed { false };
113     bool m_shouldCrashOnOverflow { true };
114 };
115
116 class CrashOnOverflow {
117 public:
118     static NO_RETURN_DUE_TO_CRASH void overflowed()
119     {
120         crash();
121     }
122
123     void clearOverflow() { }
124
125     static NO_RETURN_DUE_TO_CRASH void crash()
126     {
127         CRASH();
128     }
129
130 public:
131     bool hasOverflowed() const { return false; }
132 };
133
134 class RecordOverflow {
135 protected:
136     RecordOverflow()
137         : m_overflowed(false)
138     {
139     }
140
141     void clearOverflow()
142     {
143         m_overflowed = false;
144     }
145
146     static NO_RETURN_DUE_TO_CRASH void crash()
147     {
148         CRASH();
149     }
150
151 public:
152     bool hasOverflowed() const { return m_overflowed; }
153     void overflowed() { m_overflowed = true; }
154
155 private:
156     unsigned char m_overflowed;
157 };
158
159 template <typename T, class OverflowHandler = CrashOnOverflow> class Checked;
160 template <typename T> struct RemoveChecked;
161 template <typename T> struct RemoveChecked<Checked<T>>;
162
163 template <typename Target, typename Source, bool isTargetBigger = sizeof(Target) >= sizeof(Source), bool targetSigned = std::numeric_limits<Target>::is_signed, bool sourceSigned = std::numeric_limits<Source>::is_signed> struct BoundsChecker;
164 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false, false> {
165     static bool inBounds(Source value)
166     {
167         // Same signedness so implicit type conversion will always increase precision to widest type.
168         return value <= std::numeric_limits<Target>::max();
169     }
170 };
171 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true, true> {
172     static bool inBounds(Source value)
173     {
174         // Same signedness so implicit type conversion will always increase precision to widest type.
175         return std::numeric_limits<Target>::min() <= value && value <= std::numeric_limits<Target>::max();
176     }
177 };
178
179 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false, true> {
180     static bool inBounds(Source value)
181     {
182         // When converting value to unsigned Source, value will become a big value if value is negative.
183         // Casted value will become bigger than Target::max as Source is bigger than Target.
184         return static_cast<std::make_unsigned_t<Source>>(value) <= std::numeric_limits<Target>::max();
185     }
186 };
187
188 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true, false> {
189     static bool inBounds(Source value)
190     {
191         // The unsigned Source type has greater precision than the target so max(Target) -> Source will widen.
192         return value <= static_cast<Source>(std::numeric_limits<Target>::max());
193     }
194 };
195
196 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false, false> {
197     static bool inBounds(Source)
198     {
199         // Same sign, greater or same precision.
200         return true;
201     }
202 };
203
204 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true, true> {
205     static bool inBounds(Source)
206     {
207         // Same sign, greater or same precision.
208         return true;
209     }
210 };
211
212 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true, false> {
213     static bool inBounds(Source value)
214     {
215         // Target is signed with greater or same precision. If strictly greater, it is always safe.
216         if (sizeof(Target) > sizeof(Source))
217             return true;
218         return value <= static_cast<Source>(std::numeric_limits<Target>::max());
219     }
220 };
221
222 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false, true> {
223     static bool inBounds(Source value)
224     {
225         // Target is unsigned with greater precision.
226         return value >= 0;
227     }
228 };
229
230 template <typename Target, typename Source> static inline bool isInBounds(Source value)
231 {
232     return BoundsChecker<Target, Source>::inBounds(value);
233 }
234
235 template <typename Target, typename Source> static inline bool convertSafely(Source input, Target& output)
236 {
237     if (!isInBounds<Target>(input))
238         return false;
239     output = static_cast<Target>(input);
240     return true;
241 }
242
243 template <typename T> struct RemoveChecked {
244     typedef T CleanType;
245     static constexpr CleanType DefaultValue = 0;
246 };
247
248 template <typename T> struct RemoveChecked<Checked<T, ConditionalCrashOnOverflow>> {
249     using CleanType = typename RemoveChecked<T>::CleanType;
250     static constexpr CleanType DefaultValue = 0;
251 };
252
253 template <typename T> struct RemoveChecked<Checked<T, CrashOnOverflow>> {
254     typedef typename RemoveChecked<T>::CleanType CleanType;
255     static constexpr CleanType DefaultValue = 0;
256 };
257
258 template <typename T> struct RemoveChecked<Checked<T, RecordOverflow>> {
259     typedef typename RemoveChecked<T>::CleanType CleanType;
260     static constexpr CleanType DefaultValue = 0;
261 };
262
263 // The ResultBase and SignednessSelector are used to workaround typeof not being
264 // available in MSVC
265 template <typename U, typename V, bool uIsBigger = (sizeof(U) > sizeof(V)), bool sameSize = (sizeof(U) == sizeof(V))> struct ResultBase;
266 template <typename U, typename V> struct ResultBase<U, V, true, false> {
267     typedef U ResultType;
268 };
269
270 template <typename U, typename V> struct ResultBase<U, V, false, false> {
271     typedef V ResultType;
272 };
273
274 template <typename U> struct ResultBase<U, U, false, true> {
275     typedef U ResultType;
276 };
277
278 template <typename U, typename V, bool uIsSigned = std::numeric_limits<U>::is_signed, bool vIsSigned = std::numeric_limits<V>::is_signed> struct SignednessSelector;
279 template <typename U, typename V> struct SignednessSelector<U, V, true, true> {
280     typedef U ResultType;
281 };
282
283 template <typename U, typename V> struct SignednessSelector<U, V, false, false> {
284     typedef U ResultType;
285 };
286
287 template <typename U, typename V> struct SignednessSelector<U, V, true, false> {
288     typedef V ResultType;
289 };
290
291 template <typename U, typename V> struct SignednessSelector<U, V, false, true> {
292     typedef U ResultType;
293 };
294
295 template <typename U, typename V> struct ResultBase<U, V, false, true> {
296     typedef typename SignednessSelector<U, V>::ResultType ResultType;
297 };
298
299 template <typename U, typename V> struct Result : ResultBase<typename RemoveChecked<U>::CleanType, typename RemoveChecked<V>::CleanType> {
300 };
301
302 template <typename LHS, typename RHS, typename ResultType = typename Result<LHS, RHS>::ResultType, 
303     bool lhsSigned = std::numeric_limits<LHS>::is_signed, bool rhsSigned = std::numeric_limits<RHS>::is_signed> struct ArithmeticOperations;
304
305 template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, true, true> {
306     // LHS and RHS are signed types
307
308     // Helper function
309     static inline bool signsMatch(LHS lhs, RHS rhs)
310     {
311         return (lhs ^ rhs) >= 0;
312     }
313
314     static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
315     {
316 #if COMPILER(GCC_COMPATIBLE)
317         ResultType temp;
318         if (__builtin_add_overflow(lhs, rhs, &temp))
319             return false;
320         result = temp;
321         return true;
322 #else
323         if (signsMatch(lhs, rhs)) {
324             if (lhs >= 0) {
325                 if ((std::numeric_limits<ResultType>::max() - rhs) < lhs)
326                     return false;
327             } else {
328                 ResultType temp = lhs - std::numeric_limits<ResultType>::min();
329                 if (rhs < -temp)
330                     return false;
331             }
332         } // if the signs do not match this operation can't overflow
333         result = lhs + rhs;
334         return true;
335 #endif
336     }
337
338     static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
339     {
340 #if COMPILER(GCC_COMPATIBLE)
341         ResultType temp;
342         if (__builtin_sub_overflow(lhs, rhs, &temp))
343             return false;
344         result = temp;
345         return true;
346 #else
347         if (!signsMatch(lhs, rhs)) {
348             if (lhs >= 0) {
349                 if (lhs > std::numeric_limits<ResultType>::max() + rhs)
350                     return false;
351             } else {
352                 if (rhs > std::numeric_limits<ResultType>::max() + lhs)
353                     return false;
354             }
355         } // if the signs match this operation can't overflow
356         result = lhs - rhs;
357         return true;
358 #endif
359     }
360
361     static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
362     {
363 #if COMPILER(GCC_COMPATIBLE)
364         ResultType temp;
365         if (__builtin_mul_overflow(lhs, rhs, &temp))
366             return false;
367         result = temp;
368         return true;
369 #else
370         if (signsMatch(lhs, rhs)) {
371             if (lhs >= 0) {
372                 if (lhs && (std::numeric_limits<ResultType>::max() / lhs) < rhs)
373                     return false;
374             } else {
375                 if (static_cast<ResultType>(lhs) == std::numeric_limits<ResultType>::min() || static_cast<ResultType>(rhs) == std::numeric_limits<ResultType>::min())
376                     return false;
377                 if ((std::numeric_limits<ResultType>::max() / -lhs) < -rhs)
378                     return false;
379             }
380         } else {
381             if (lhs < 0) {
382                 if (rhs && lhs < (std::numeric_limits<ResultType>::min() / rhs))
383                     return false;
384             } else {
385                 if (lhs && rhs < (std::numeric_limits<ResultType>::min() / lhs))
386                     return false;
387             }
388         }
389         result = lhs * rhs;
390         return true;
391 #endif
392     }
393
394     static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; }
395
396 };
397
398 template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, false, false> {
399     // LHS and RHS are unsigned types so bounds checks are nice and easy
400     static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
401     {
402 #if COMPILER(GCC_COMPATIBLE)
403         ResultType temp;
404         if (__builtin_add_overflow(lhs, rhs, &temp))
405             return false;
406         result = temp;
407         return true;
408 #else
409         ResultType temp = lhs + rhs;
410         if (temp < lhs)
411             return false;
412         result = temp;
413         return true;
414 #endif
415     }
416
417     static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
418     {
419 #if COMPILER(GCC_COMPATIBLE)
420         ResultType temp;
421         if (__builtin_sub_overflow(lhs, rhs, &temp))
422             return false;
423         result = temp;
424         return true;
425 #else
426         ResultType temp = lhs - rhs;
427         if (temp > lhs)
428             return false;
429         result = temp;
430         return true;
431 #endif
432     }
433
434     static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
435     {
436 #if COMPILER(GCC_COMPATIBLE)
437         ResultType temp;
438         if (__builtin_mul_overflow(lhs, rhs, &temp))
439             return false;
440         result = temp;
441         return true;
442 #else
443         if (!lhs || !rhs) {
444             result = 0;
445             return true;
446         }
447         if (std::numeric_limits<ResultType>::max() / lhs < rhs)
448             return false;
449         result = lhs * rhs;
450         return true;
451 #endif
452     }
453
454     static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; }
455
456 };
457
458 template <typename ResultType> struct ArithmeticOperations<int, unsigned, ResultType, true, false> {
459     static inline bool add(int64_t lhs, int64_t rhs, ResultType& result)
460     {
461 #if COMPILER(GCC_COMPATIBLE)
462         ResultType temp;
463         if (__builtin_add_overflow(lhs, rhs, &temp))
464             return false;
465         result = temp;
466         return true;
467 #else
468         int64_t temp = lhs + rhs;
469         if (temp < std::numeric_limits<ResultType>::min())
470             return false;
471         if (temp > std::numeric_limits<ResultType>::max())
472             return false;
473         result = static_cast<ResultType>(temp);
474         return true;
475 #endif
476     }
477     
478     static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result)
479     {
480 #if COMPILER(GCC_COMPATIBLE)
481         ResultType temp;
482         if (__builtin_sub_overflow(lhs, rhs, &temp))
483             return false;
484         result = temp;
485         return true;
486 #else
487         int64_t temp = lhs - rhs;
488         if (temp < std::numeric_limits<ResultType>::min())
489             return false;
490         if (temp > std::numeric_limits<ResultType>::max())
491             return false;
492         result = static_cast<ResultType>(temp);
493         return true;
494 #endif
495     }
496
497     static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result)
498     {
499 #if COMPILER(GCC_COMPATIBLE)
500         ResultType temp;
501         if (__builtin_mul_overflow(lhs, rhs, &temp))
502             return false;
503         result = temp;
504         return true;
505 #else
506         int64_t temp = lhs * rhs;
507         if (temp < std::numeric_limits<ResultType>::min())
508             return false;
509         if (temp > std::numeric_limits<ResultType>::max())
510             return false;
511         result = static_cast<ResultType>(temp);
512         return true;
513 #endif
514     }
515
516     static inline bool equals(int lhs, unsigned rhs)
517     {
518         return static_cast<int64_t>(lhs) == static_cast<int64_t>(rhs);
519     }
520 };
521
522 template <typename ResultType> struct ArithmeticOperations<unsigned, int, ResultType, false, true> {
523     static inline bool add(int64_t lhs, int64_t rhs, ResultType& result)
524     {
525         return ArithmeticOperations<int, unsigned, ResultType>::add(rhs, lhs, result);
526     }
527     
528     static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result)
529     {
530         return ArithmeticOperations<int, unsigned, ResultType>::sub(lhs, rhs, result);
531     }
532
533     static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result)
534     {
535         return ArithmeticOperations<int, unsigned, ResultType>::multiply(lhs, rhs, result);
536     }
537
538     static inline bool equals(unsigned lhs, int rhs)
539     {
540         return ArithmeticOperations<int, unsigned, ResultType>::equals(rhs, lhs);
541     }
542 };
543
544 template <class OverflowHandler, typename = std::enable_if_t<!std::is_scalar<OverflowHandler>::value>>
545 inline constexpr bool observesOverflow() { return true; }
546
547 template <>
548 inline constexpr bool observesOverflow<AssertNoOverflow>() { return !ASSERT_DISABLED; }
549
550 template <typename U, typename V, typename R> static inline bool safeAdd(U lhs, V rhs, R& result)
551 {
552     return ArithmeticOperations<U, V, R>::add(lhs, rhs, result);
553     return true;
554 }
555
556 template <class OverflowHandler, typename U, typename V, typename R, typename = std::enable_if_t<!std::is_scalar<OverflowHandler>::value>>
557 static inline bool safeAdd(U lhs, V rhs, R& result)
558 {
559     if (observesOverflow<OverflowHandler>())
560         return safeAdd(lhs, rhs, result);
561     result = lhs + rhs;
562     return true;
563 }
564
565 template <typename U, typename V, typename R> static inline bool safeSub(U lhs, V rhs, R& result)
566 {
567     return ArithmeticOperations<U, V, R>::sub(lhs, rhs, result);
568 }
569
570 template <class OverflowHandler, typename U, typename V, typename R, typename = std::enable_if_t<!std::is_scalar<OverflowHandler>::value>>
571 static inline bool safeSub(U lhs, V rhs, R& result)
572 {
573     if (observesOverflow<OverflowHandler>())
574         return safeSub(lhs, rhs, result);
575     result = lhs - rhs;
576     return true;
577 }
578
579 template <typename U, typename V, typename R> static inline bool safeMultiply(U lhs, V rhs, R& result)
580 {
581     return ArithmeticOperations<U, V, R>::multiply(lhs, rhs, result);
582 }
583
584 template <class OverflowHandler, typename U, typename V, typename R, typename = std::enable_if_t<!std::is_scalar<OverflowHandler>::value>>
585 static inline bool safeMultiply(U lhs, V rhs, R& result)
586 {
587     if (observesOverflow<OverflowHandler>())
588         return safeMultiply(lhs, rhs, result);
589     result = lhs * rhs;
590     return true;
591 }
592
593 template <typename U, typename V> static inline bool safeEquals(U lhs, V rhs)
594 {
595     return ArithmeticOperations<U, V>::equals(lhs, rhs);
596 }
597
598 enum ResultOverflowedTag { ResultOverflowed };
599     
600 template <typename T, class OverflowHandler> class Checked : public OverflowHandler {
601 public:
602     template <typename _T, class _OverflowHandler> friend class Checked;
603     Checked()
604         : m_value(0)
605     {
606     }
607
608     Checked(ResultOverflowedTag)
609         : m_value(0)
610     {
611         this->overflowed();
612     }
613
614     Checked(const Checked& value)
615     {
616         if (value.hasOverflowed())
617             this->overflowed();
618         m_value = static_cast<T>(value.m_value);
619     }
620
621     template <typename U> Checked(U value)
622     {
623         if (!isInBounds<T>(value))
624             this->overflowed();
625         m_value = static_cast<T>(value);
626     }
627     
628     template <typename V> Checked(const Checked<T, V>& rhs)
629         : m_value(rhs.m_value)
630     {
631         if (rhs.hasOverflowed())
632             this->overflowed();
633     }
634     
635     template <typename U> Checked(const Checked<U, OverflowHandler>& rhs)
636         : OverflowHandler(rhs)
637     {
638         if (!isInBounds<T>(rhs.m_value))
639             this->overflowed();
640         m_value = static_cast<T>(rhs.m_value);
641     }
642     
643     template <typename U, typename V> Checked(const Checked<U, V>& rhs)
644     {
645         if (rhs.hasOverflowed())
646             this->overflowed();
647         if (!isInBounds<T>(rhs.m_value))
648             this->overflowed();
649         m_value = static_cast<T>(rhs.m_value);
650     }
651     
652     const Checked& operator=(Checked rhs)
653     {
654         this->clearOverflow();
655         if (rhs.hasOverflowed())
656             this->overflowed();
657         m_value = static_cast<T>(rhs.m_value);
658         return *this;
659     }
660     
661     template <typename U> const Checked& operator=(U value)
662     {
663         return *this = Checked(value);
664     }
665     
666     template <typename U, typename V> const Checked& operator=(const Checked<U, V>& rhs)
667     {
668         return *this = Checked(rhs);
669     }
670     
671     // prefix
672     const Checked& operator++()
673     {
674         if (m_value == std::numeric_limits<T>::max())
675             this->overflowed();
676         m_value++;
677         return *this;
678     }
679     
680     const Checked& operator--()
681     {
682         if (m_value == std::numeric_limits<T>::min())
683             this->overflowed();
684         m_value--;
685         return *this;
686     }
687     
688     // postfix operators
689     const Checked operator++(int)
690     {
691         if (m_value == std::numeric_limits<T>::max())
692             this->overflowed();
693         return Checked(m_value++);
694     }
695     
696     const Checked operator--(int)
697     {
698         if (m_value == std::numeric_limits<T>::min())
699             this->overflowed();
700         return Checked(m_value--);
701     }
702     
703     // Boolean operators
704     bool operator!() const
705     {
706         if (this->hasOverflowed())
707             this->crash();
708         return !m_value;
709     }
710
711     explicit operator bool() const
712     {
713         if (this->hasOverflowed())
714             this->crash();
715         return m_value;
716     }
717
718     // Value accessors. unsafeGet() will crash if there's been an overflow.
719     template<typename U = T>
720     U unsafeGet() const
721     {
722         if (this->hasOverflowed())
723             this->crash();
724         return static_cast<U>(m_value);
725     }
726     
727     inline CheckedState safeGet(T& value) const WARN_UNUSED_RETURN
728     {
729         value = m_value;
730         if (this->hasOverflowed())
731             return CheckedState::DidOverflow;
732         return CheckedState::DidNotOverflow;
733     }
734
735     // Mutating assignment
736     template <typename U> const Checked operator+=(U rhs)
737     {
738         if (!safeAdd<OverflowHandler>(m_value, rhs, m_value))
739             this->overflowed();
740         return *this;
741     }
742
743     template <typename U> const Checked operator-=(U rhs)
744     {
745         if (!safeSub<OverflowHandler>(m_value, rhs, m_value))
746             this->overflowed();
747         return *this;
748     }
749
750     template <typename U> const Checked operator*=(U rhs)
751     {
752         if (!safeMultiply<OverflowHandler>(m_value, rhs, m_value))
753             this->overflowed();
754         return *this;
755     }
756
757     const Checked operator*=(double rhs)
758     {
759         double result = rhs * m_value;
760         // Handle +/- infinity and NaN
761         if (!(std::numeric_limits<T>::min() <= result && std::numeric_limits<T>::max() >= result))
762             this->overflowed();
763         m_value = (T)result;
764         return *this;
765     }
766
767     const Checked operator*=(float rhs)
768     {
769         return *this *= (double)rhs;
770     }
771     
772     template <typename U, typename V> const Checked operator+=(Checked<U, V> rhs)
773     {
774         if (rhs.hasOverflowed())
775             this->overflowed();
776         return *this += rhs.m_value;
777     }
778
779     template <typename U, typename V> const Checked operator-=(Checked<U, V> rhs)
780     {
781         if (rhs.hasOverflowed())
782             this->overflowed();
783         return *this -= rhs.m_value;
784     }
785
786     template <typename U, typename V> const Checked operator*=(Checked<U, V> rhs)
787     {
788         if (rhs.hasOverflowed())
789             this->overflowed();
790         return *this *= rhs.m_value;
791     }
792
793     // Equality comparisons
794     template <typename V> bool operator==(Checked<T, V> rhs)
795     {
796         return unsafeGet() == rhs.unsafeGet();
797     }
798
799     template <typename U> bool operator==(U rhs)
800     {
801         if (this->hasOverflowed())
802             this->crash();
803         return safeEquals(m_value, rhs);
804     }
805     
806     template <typename U, typename V> const Checked operator==(Checked<U, V> rhs)
807     {
808         return unsafeGet() == Checked(rhs.unsafeGet());
809     }
810
811     template <typename U> bool operator!=(U rhs)
812     {
813         return !(*this == rhs);
814     }
815
816     // Other comparisons
817     template <typename V> bool operator<(Checked<T, V> rhs) const
818     {
819         return unsafeGet() < rhs.unsafeGet();
820     }
821
822     bool operator<(T rhs) const
823     {
824         return unsafeGet() < rhs;
825     }
826
827     template <typename V> bool operator<=(Checked<T, V> rhs) const
828     {
829         return unsafeGet() <= rhs.unsafeGet();
830     }
831
832     bool operator<=(T rhs) const
833     {
834         return unsafeGet() <= rhs;
835     }
836
837     template <typename V> bool operator>(Checked<T, V> rhs) const
838     {
839         return unsafeGet() > rhs.unsafeGet();
840     }
841
842     bool operator>(T rhs) const
843     {
844         return unsafeGet() > rhs;
845     }
846
847     template <typename V> bool operator>=(Checked<T, V> rhs) const
848     {
849         return unsafeGet() >= rhs.unsafeGet();
850     }
851
852     bool operator>=(T rhs) const
853     {
854         return unsafeGet() >= rhs;
855     }
856
857 private:
858     // Disallow implicit conversion of floating point to integer types
859     Checked(float);
860     Checked(double);
861     void operator=(float);
862     void operator=(double);
863     void operator+=(float);
864     void operator+=(double);
865     void operator-=(float);
866     void operator-=(double);
867     T m_value;
868 };
869
870 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs)
871 {
872     U x = 0;
873     V y = 0;
874     bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow;
875     typename Result<U, V>::ResultType result = 0;
876     overflowed |= !safeAdd<OverflowHandler>(x, y, result);
877     if (overflowed)
878         return ResultOverflowed;
879     return result;
880 }
881
882 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs)
883 {
884     U x = 0;
885     V y = 0;
886     bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow;
887     typename Result<U, V>::ResultType result = 0;
888     overflowed |= !safeSub<OverflowHandler>(x, y, result);
889     if (overflowed)
890         return ResultOverflowed;
891     return result;
892 }
893
894 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs)
895 {
896     U x = 0;
897     V y = 0;
898     bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow;
899     typename Result<U, V>::ResultType result = 0;
900     overflowed |= !safeMultiply<OverflowHandler>(x, y, result);
901     if (overflowed)
902         return ResultOverflowed;
903     return result;
904 }
905
906 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(Checked<U, OverflowHandler> lhs, V rhs)
907 {
908     return lhs + Checked<V, OverflowHandler>(rhs);
909 }
910
911 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(Checked<U, OverflowHandler> lhs, V rhs)
912 {
913     return lhs - Checked<V, OverflowHandler>(rhs);
914 }
915
916 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(Checked<U, OverflowHandler> lhs, V rhs)
917 {
918     return lhs * Checked<V, OverflowHandler>(rhs);
919 }
920
921 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(U lhs, Checked<V, OverflowHandler> rhs)
922 {
923     return Checked<U, OverflowHandler>(lhs) + rhs;
924 }
925
926 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(U lhs, Checked<V, OverflowHandler> rhs)
927 {
928     return Checked<U, OverflowHandler>(lhs) - rhs;
929 }
930
931 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(U lhs, Checked<V, OverflowHandler> rhs)
932 {
933     return Checked<U, OverflowHandler>(lhs) * rhs;
934 }
935
936 // Convenience typedefs.
937 typedef Checked<int8_t, RecordOverflow> CheckedInt8;
938 typedef Checked<uint8_t, RecordOverflow> CheckedUint8;
939 typedef Checked<int16_t, RecordOverflow> CheckedInt16;
940 typedef Checked<uint16_t, RecordOverflow> CheckedUint16;
941 typedef Checked<int32_t, RecordOverflow> CheckedInt32;
942 typedef Checked<uint32_t, RecordOverflow> CheckedUint32;
943 typedef Checked<int64_t, RecordOverflow> CheckedInt64;
944 typedef Checked<uint64_t, RecordOverflow> CheckedUint64;
945 typedef Checked<size_t, RecordOverflow> CheckedSize;
946
947 template<typename T, typename U>
948 Checked<T, RecordOverflow> checkedSum(U value)
949 {
950     return Checked<T, RecordOverflow>(value);
951 }
952 template<typename T, typename U, typename... Args>
953 Checked<T, RecordOverflow> checkedSum(U value, Args... args)
954 {
955     return Checked<T, RecordOverflow>(value) + checkedSum<T>(args...);
956 }
957
958 // Sometimes, you just want to check if some math would overflow - the code to do the math is
959 // already in place, and you want to guard it.
960
961 template<typename T, typename... Args> bool sumOverflows(Args... args)
962 {
963     return checkedSum<T>(args...).hasOverflowed();
964 }
965
966 template<typename T, typename U> bool differenceOverflows(U left, U right)
967 {
968     return (Checked<T, RecordOverflow>(left) - Checked<T, RecordOverflow>(right)).hasOverflowed();
969 }
970
971 template<typename T, typename U>
972 Checked<T, RecordOverflow> checkedProduct(U value)
973 {
974     return Checked<T, RecordOverflow>(value);
975 }
976 template<typename T, typename U, typename... Args>
977 Checked<T, RecordOverflow> checkedProduct(U value, Args... args)
978 {
979     return Checked<T, RecordOverflow>(value) * checkedProduct<T>(args...);
980 }
981
982 // Sometimes, you just want to check if some math would overflow - the code to do the math is
983 // already in place, and you want to guard it.
984
985 template<typename T, typename... Args> bool productOverflows(Args... args)
986 {
987     return checkedProduct<T>(args...).hasOverflowed();
988 }
989
990 }
991
992 using WTF::AssertNoOverflow;
993 using WTF::Checked;
994 using WTF::CheckedState;
995 using WTF::CheckedInt8;
996 using WTF::CheckedUint8;
997 using WTF::CheckedInt16;
998 using WTF::CheckedUint16;
999 using WTF::CheckedInt32;
1000 using WTF::CheckedUint32;
1001 using WTF::CheckedInt64;
1002 using WTF::CheckedUint64;
1003 using WTF::CheckedSize;
1004 using WTF::ConditionalCrashOnOverflow;
1005 using WTF::CrashOnOverflow;
1006 using WTF::RecordOverflow;
1007 using WTF::checkedSum;
1008 using WTF::differenceOverflows;
1009 using WTF::productOverflows;
1010 using WTF::sumOverflows;