xref: /reactos/sdk/include/ucrt/safeint.h (revision 04e0dc4a)
1 /***
2 *safeint.h - SafeInt class and free-standing functions used to prevent arithmetic overflows
3 *
4 *       Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose:
7 *
8 *       The SafeInt class is designed to have as low an overhead as possible
9 *       while still ensuring that all integer operations are conducted safely.
10 *       Nearly every operator has been overloaded, with a very few exceptions.
11 *
12 *       A usability-safety trade-off has been made to help ensure safety. This
13 *       requires that every operation return either a SafeInt or a bool. If we
14 *       allowed an operator to return a base integer type T, then the following
15 *       can happen:
16 *
17 *       char i = SafeInt<char>(32) * 2 + SafeInt<char>(16) * 4;
18 *
19 *       The * operators take precedence, get overloaded, return a char, and then
20 *       you have:
21 *
22 *       char i = (char)64 + (char)64; //overflow!
23 *
24 *       This situation would mean that safety would depend on usage, which isn't
25 *       acceptable.
26 *
27 *       One key operator that is missing is an implicit cast to type T. The reason for
28 *       this is that if there is an implicit cast operator, then we end up with
29 *       an ambiguous compile-time precedence. Because of this amiguity, there
30 *       are two methods that are provided:
31 *
32 *       Casting operators for every native integer type
33 *
34 *       SafeInt::Ptr()   - returns the address of the internal integer
35 *
36 *       The SafeInt class should be used in any circumstances where ensuring
37 *       integrity of the calculations is more important than performance. See Performance
38 *       Notes below for additional information.
39 *
40 *       Many of the conditionals will optimize out or be inlined for a release
41 *       build (especially with /Ox), but it does have significantly more overhead,
42 *       especially for signed numbers. If you do not _require_ negative numbers, use
43 *       unsigned integer types - certain types of problems cannot occur, and this class
44 *       performs most efficiently.
45 *
46 *       Here's an example of when the class should ideally be used -
47 *
48 *       void* AllocateMemForStructs(int StructSize, int HowMany)
49 *       {
50 *          SafeInt<unsigned long> s(StructSize);
51 *
52 *          s *= HowMany;
53 *
54 *          return malloc(s);
55 *
56 *       }
57 *
58 *       Here's when it should NOT be used:
59 *
60 *       void foo()
61 *       {
62 *         int i;
63 *
64 *         for(i = 0; i < 0xffff; i++)
65 *           ....
66 *       }
67 *
68 *       Error handling - a SafeInt class will throw exceptions if something
69 *       objectionable happens. The exceptions are SafeIntException classes,
70 *       which contain an enum as a code.
71 *
72 *       Typical usage might be:
73 *
74 *       bool foo()
75 *       {
76 *         SafeInt<unsigned long> s; //note that s == 0 unless set
77 *
78 *         try{
79 *           s *= 23;
80 *           ....
81 *         }
82 *         catch(SafeIntException err)
83 *         {
84 *            //handle errors here
85 *         }
86 *       }
87 *
88 *       SafeInt accepts an error policy as an optional template parameter.
89 *       We provide two error policy along with SafeInt: SafeIntErrorPolicy_SafeIntException, which
90 *       throws SafeIntException in case of error, and SafeIntErrorPolicy_InvalidParameter, which
91 *       calls _invalid_parameter to terminate the program.
92 *
93 *       You can replace the error policy class with any class you like. This is accomplished by:
94 *       1) Create a class that has the following interface:
95 *
96 *         struct YourSafeIntErrorPolicy
97 *         {
98 *             static __declspec(noreturn) void __stdcall SafeIntOnOverflow()
99 *             {
100 *                 throw YourException( YourSafeIntArithmeticOverflowError );
101 *                 // or do something else which will terminate the program
102 *             }
103 *
104 *             static __declspec(noreturn) void __stdcall SafeIntOnDivZero()
105 *             {
106 *                 throw YourException( YourSafeIntDivideByZeroError );
107 *                 // or do something else which will terminate the program
108 *             }
109 *         };
110 *
111 *       Note that you don't have to throw C++ exceptions, you can throw Win32 exceptions, or do
112 *       anything you like, just don't return from the call back into the code.
113 *
114 *       2) Either explicitly declare SafeInts like so:
115 *          SafeInt< int, YourSafeIntErrorPolicy > si;
116 *       or, before including SafeInt:
117 *          #define _SAFEINT_DEFAULT_ERROR_POLICY ::YourSafeIntErrorPolicy
118 *
119 *       Performance:
120 *
121 *       Due to the highly nested nature of this class, you can expect relatively poor
122 *       performance in unoptimized code. In tests of optimized code vs. correct inline checks
123 *       in native code, this class has been found to take approximately 8% more CPU time (this varies),
124 *       most of which is due to exception handling.
125 *
126 *       Binary Operators:
127 *
128 *       All of the binary operators have certain assumptions built into the class design.
129 *       This is to ensure correctness. Notes on each class of operator follow:
130 *
131 *       Arithmetic Operators (*,/,+,-,%)
132 *       There are three possible variants:
133 *       SafeInt< T, E > op SafeInt< T, E >
134 *       SafeInt< T, E > op U
135 *       U op SafeInt< T, E >
136 *
137 *       The SafeInt< T, E > op SafeInt< U, E > variant is explicitly not supported, and if you try to do
138 *       this the compiler with throw the following error:
139 *
140 *       error C2593: 'operator *' is ambiguous
141 *
142 *       This is because the arithmetic operators are required to return a SafeInt of some type.
143 *       The compiler cannot know whether you'd prefer to get a type T or a type U returned. If
144 *       you need to do this, you need to extract the value contained within one of the two using
145 *       the casting operator. For example:
146 *
147 *       SafeInt< T, E > t, result;
148 *       SafeInt< U, E > u;
149 *
150 *       result = t * (U)u;
151 *
152 *       Comparison Operators:
153 *
154 *       Because each of these operators return type bool, mixing SafeInts of differing types is
155 *       allowed.
156 *
157 *       Shift Operators:
158 *
159 *       Shift operators always return the type on the left hand side of the operator. Mixed type
160 *       operations are allowed because the return type is always known.
161 *
162 *       Boolean Operators:
163 *
164 *       Like comparison operators, these overloads always return type bool, and mixed-type SafeInts
165 *       are allowed. Additionally, specific overloads exist for type bool on both sides of the
166 *       operator.
167 *
168 *       Binary Operators:
169 *
170 *       Mixed-type operations are discouraged, however some provision has been made in order to
171 *       enable things like:
172 *
173 *       SafeInt<char> c = 2;
174 *
175 *       if(c & 0x02)
176 *         ...
177 *
178 *       The "0x02" is actually an int, and it needs to work.
179 *       In the case of binary operations on integers smaller than 32-bit, or of mixed type, corner
180 *       cases do exist where you could get unexpected results. In any case where SafeInt returns a different
181 *       result than the underlying operator, it will call _ASSERTE(). You should examine your code and cast things
182 *       properly so that you are not programming with side effects.
183 *
184 *       Comparison Operators and ANSI Conversions:
185 *
186 *       The comparison operator behavior in this class varies from the ANSI definition.
187 *       As an example, consider the following:
188 *
189 *       unsigned int l = 0xffffffff;
190 *       char c = -1;
191 *
192 *       if(c == l)
193 *         printf("Why is -1 equal to 4 billion???\n");
194 *
195 *       The problem here is that c gets cast to an int, now has a value of 0xffffffff, and then gets
196 *       cast again to an unsigned int, losing the true value. This behavior is despite the fact that
197 *       an __int64 exists, and the following code will yield a different (and intuitively correct)
198 *       answer:
199 *
200 *       if((__int64)c == (__int64)l))
201 *         printf("Why is -1 equal to 4 billion???\n");
202 *       else
203 *         printf("Why doesn't the compiler upcast to 64-bits when needed?\n");
204 *
205 *       Note that combinations with smaller integers won't display the problem - if you
206 *       changed "unsigned int" above to "unsigned short", you'd get the right answer.
207 *
208 *       If you prefer to retain the ANSI standard behavior insert, before including safeint.h:
209 *
210 *       #define _SAFEINT_ANSI_CONVERSIONS 1
211 *
212 *       into your source. Behavior differences occur in the following cases:
213 *       8, 16, and 32-bit signed int, unsigned 32-bit int
214 *       any signed int, unsigned 64-bit int
215 *       Note - the signed int must be negative to show the problem
216 *
217 ****/
218 
219 #pragma once
220 
221 #if !defined(RC_INVOKED)
222 
223 #include <corecrt.h>
224 #include <crtdbg.h>
225 
226 // Disable warnings hit under /Wall:
227 // C4514: unreferenced inline function has been removed (/Wall)
228 // C4710: function not inlined (/Wall)
229 #pragma warning(push)
230 #pragma warning(disable: 4514)
231 #pragma warning(disable: 4710)
232 
233 #if !defined (_SAFEINT_DEFAULT_ERROR_POLICY)
234 #define _SAFEINT_DEFAULT_ERROR_POLICY SafeIntErrorPolicy_SafeIntException
235 #endif  /* !defined (_SAFEINT_DEFAULT_ERROR_POLICY) */
236 
237 #if !defined (_SAFEINT_SHIFT_ASSERT)
238 #define _SAFEINT_SHIFT_ASSERT(x) _ASSERTE(x)
239 #endif  /* !defined (_SAFEINT_SHIFT_ASSERT) */
240 
241 #if !defined (_SAFEINT_BINARY_ASSERT)
242 #define _SAFEINT_BINARY_ASSERT(x) _ASSERTE(x)
243 #endif  /* !defined (_SAFEINT_BINARY_ASSERT) */
244 
245 #if !defined (_SAFEINT_EXCEPTION_ASSERT)
246 #define _SAFEINT_EXCEPTION_ASSERT()
247 #endif  /* !defined (_SAFEINT_EXCEPTION_ASSERT) */
248 
249 // by default, SafeInt will accept negation of an unsigned int;
250 // if you wish to disable it or assert, you can define the following
251 // macro to be a static assert or a runtime assert
252 #if !defined (_SAFEINT_UNSIGNED_NEGATION_BEHAVIOR)
253 #define _SAFEINT_UNSIGNED_NEGATION_BEHAVIOR()
254 #endif  /* !defined (_SAFEINT_UNSIGNED_NEGATION_BEHAVIOR) */
255 
256 // See above "Comparison Operators and ANSI Conversions" for an explanation
257 // of _SAFEINT_USE_ANSI_CONVERSIONS
258 #if !defined (_SAFEINT_USE_ANSI_CONVERSIONS)
259 #define _SAFEINT_USE_ANSI_CONVERSIONS 0
260 #endif  /* !defined (_SAFEINT_USE_ANSI_CONVERSIONS) */
261 
262 #pragma pack(push, _CRT_PACKING)
263 
264 namespace msl
265 {
266 
267 namespace utilities
268 {
269 
270 enum SafeIntError
271 {
272     SafeIntNoError = 0,
273     SafeIntArithmeticOverflow,
274     SafeIntDivideByZero
275 };
276 
277 } // namespace utilities
278 
279 } // namespace msl
280 
281 #include "safeint_internal.h"
282 
283 namespace msl
284 {
285 
286 namespace utilities
287 {
288 
289 class SafeIntException
290 {
291 public:
SafeIntException()292     SafeIntException() { m_code = SafeIntNoError; }
SafeIntException(SafeIntError code)293     SafeIntException( SafeIntError code )
294     {
295         m_code = code;
296     }
297     SafeIntError m_code;
298 };
299 
300 struct SafeIntErrorPolicy_SafeIntException
301 {
SafeIntOnOverflowSafeIntErrorPolicy_SafeIntException302     static __declspec(noreturn) void SafeIntOnOverflow()
303     {
304         _SAFEINT_EXCEPTION_ASSERT();
305         throw SafeIntException( SafeIntArithmeticOverflow );
306     }
307 
SafeIntOnDivZeroSafeIntErrorPolicy_SafeIntException308     static __declspec(noreturn) void SafeIntOnDivZero()
309     {
310         _SAFEINT_EXCEPTION_ASSERT();
311         throw SafeIntException( SafeIntDivideByZero );
312     }
313 };
314 
315 struct SafeIntErrorPolicy_InvalidParameter
316 {
SafeIntOnOverflowSafeIntErrorPolicy_InvalidParameter317     static __declspec(noreturn) void SafeIntOnOverflow()
318     {
319         _SAFEINT_EXCEPTION_ASSERT();
320         _CRT_SECURE_INVALID_PARAMETER("SafeInt Arithmetic Overflow");
321     }
322 
SafeIntOnDivZeroSafeIntErrorPolicy_InvalidParameter323     static __declspec(noreturn) void SafeIntOnDivZero()
324     {
325         _SAFEINT_EXCEPTION_ASSERT();
326         _CRT_SECURE_INVALID_PARAMETER("SafeInt Divide By Zero");
327     }
328 };
329 
330 // Free-standing functions that can be used where you only need to check one operation
331 // non-class helper function so that you can check for a cast's validity
332 // and handle errors how you like
333 
334 template < typename T, typename U >
SafeCast(const T From,U & To)335 inline bool SafeCast( const T From, U& To ) throw()
336 {
337     return (details::SafeCastHelper< U, T,
338         details::SafeIntErrorPolicy_NoThrow >::Cast( From, To ) == SafeIntNoError);
339 }
340 
341 template < typename T, typename U >
SafeEquals(const T t,const U u)342 inline bool SafeEquals( const T t, const U u ) throw()
343 {
344     return details::EqualityTest< T, U >::IsEquals( t, u );
345 }
346 
347 template < typename T, typename U >
SafeNotEquals(const T t,const U u)348 inline bool SafeNotEquals( const T t, const U u ) throw()
349 {
350     return !details::EqualityTest< T, U >::IsEquals( t, u );
351 }
352 
353 template < typename T, typename U >
SafeGreaterThan(const T t,const U u)354 inline bool SafeGreaterThan( const T t, const U u ) throw()
355 {
356     return details::GreaterThanTest< T, U >::GreaterThan( t, u );
357 }
358 
359 template < typename T, typename U >
SafeGreaterThanEquals(const T t,const U u)360 inline bool SafeGreaterThanEquals( const T t, const U u ) throw()
361 {
362     return !details::GreaterThanTest< U, T >::GreaterThan( u, t );
363 }
364 
365 template < typename T, typename U >
SafeLessThan(const T t,const U u)366 inline bool SafeLessThan( const T t, const U u ) throw()
367 {
368     return details::GreaterThanTest< U, T >::GreaterThan( u, t );
369 }
370 
371 template < typename T, typename U >
SafeLessThanEquals(const T t,const U u)372 inline bool SafeLessThanEquals( const T t, const U u ) throw()
373 {
374     return !details::GreaterThanTest< T, U >::GreaterThan( t, u );
375 }
376 
377 template < typename T, typename U >
SafeModulus(const T & t,const U & u,T & result)378 inline bool SafeModulus( const T& t, const U& u, T& result ) throw()
379 {
380     return ( details::ModulusHelper< T, U, details::SafeIntErrorPolicy_NoThrow >::Modulus( t, u, result ) == SafeIntNoError );
381 }
382 
383 template < typename T, typename U >
SafeMultiply(T t,U u,T & result)384 inline bool SafeMultiply( T t, U u, T& result ) throw()
385 {
386     return ( details::MultiplicationHelper< T, U,
387         details::SafeIntErrorPolicy_NoThrow >::Multiply( t, u, result ) == SafeIntNoError );
388 }
389 
390 template < typename T, typename U >
SafeDivide(T t,U u,T & result)391 inline bool SafeDivide( T t, U u, T& result ) throw()
392 {
393     return ( details::DivisionHelper< T, U,
394         details::SafeIntErrorPolicy_NoThrow >::Divide( t, u, result ) == SafeIntNoError );
395 }
396 
397 template < typename T, typename U >
SafeAdd(T t,U u,T & result)398 inline bool SafeAdd( T t, U u, T& result ) throw()
399 {
400     return ( details::AdditionHelper< T, U,
401         details::SafeIntErrorPolicy_NoThrow >::Addition( t, u, result ) == SafeIntNoError );
402 }
403 
404 template < typename T, typename U >
SafeSubtract(T t,U u,T & result)405 inline bool SafeSubtract( T t, U u, T& result ) throw()
406 {
407     return ( details::SubtractionHelper< T, U,
408         details::SafeIntErrorPolicy_NoThrow >::Subtract( t, u, result ) == SafeIntNoError );
409 }
410 
411 // SafeInt class
412 template < typename T, typename E = _SAFEINT_DEFAULT_ERROR_POLICY >
413 class SafeInt
414 {
415 public:
SafeInt()416     SafeInt() throw()
417     {
418         static_assert( details::NumericType< T >::isInt , "SafeInt<T>: T needs to be an integer type" );
419         m_int = 0;
420     }
421 
422     // Having a constructor for every type of int
423     // avoids having the compiler evade our checks when doing implicit casts -
424     // e.g., SafeInt<char> s = 0x7fffffff;
throw()425     SafeInt( const T& i ) throw()
426     {
427         static_assert( details::NumericType< T >::isInt , "SafeInt<T>: T needs to be an integer type" );
428         //always safe
429         m_int = i;
430     }
431 
432     // provide explicit boolean converter
throw()433     SafeInt( bool b ) throw()
434     {
435         static_assert( details::NumericType< T >::isInt , "SafeInt<T>: T needs to be an integer type" );
436         m_int = b ? 1 : 0;
437     }
438 
439     template < typename U >
SafeInt(const SafeInt<U,E> & u)440     SafeInt(const SafeInt< U, E >& u)
441     {
442         static_assert( details::NumericType< T >::isInt , "SafeInt<T>: T needs to be an integer type" );
443         *this = SafeInt< T, E >( (U)u );
444     }
445 
446     template < typename U >
SafeInt(const U & i)447     SafeInt( const U& i )
448     {
449         static_assert( details::NumericType< T >::isInt , "SafeInt<T>: T needs to be an integer type" );
450         // SafeCast will throw exceptions if i won't fit in type T
451         details::SafeCastHelper< T, U, E >::Cast( i, m_int );
452     }
453 
454     // now start overloading operators
455     // assignment operator
456     // constructors exist for all int types and will ensure safety
457 
458     template < typename U >
459     SafeInt< T, E >& operator =( const U& rhs )
460     {
461         // use constructor to test size
462         // constructor is optimized to do minimal checking based
463         // on whether T can contain U
464         // note - do not change this
465         *this = SafeInt< T, E >( rhs );
466         return *this;
467     }
468 
throw()469     SafeInt< T, E >& operator =( const T& rhs ) throw()
470     {
471         m_int = rhs;
472         return *this;
473     }
474 
475     template < typename U >
476     SafeInt< T, E >& operator =( const SafeInt< U, E >& rhs )
477     {
478         details::SafeCastHelper< T, U, E >::Cast( rhs.Ref(), m_int );
479         return *this;
480     }
481 
throw()482     SafeInt< T, E >& operator =( const SafeInt< T, E >& rhs ) throw()
483     {
484         m_int = rhs.m_int;
485         return *this;
486     }
487 
488     // Casting operators
489 
throw()490     operator bool() const throw()
491     {
492         return !!m_int;
493     }
494 
495     operator char() const
496     {
497         char val;
498         details::SafeCastHelper< char, T, E >::Cast( m_int, val );
499         return val;
500     }
501 
502     operator signed char() const
503     {
504         signed char val;
505         details::SafeCastHelper< signed char, T, E >::Cast( m_int, val );
506         return val;
507     }
508 
509     operator unsigned char() const
510     {
511         unsigned char val;
512         details::SafeCastHelper< unsigned char, T, E >::Cast( m_int, val );
513         return val;
514     }
515 
__int16()516     operator __int16() const
517     {
518         __int16 val;
519         details::SafeCastHelper< __int16, T, E >::Cast( m_int, val );
520         return val;
521     }
522 
__int16()523     operator unsigned __int16() const
524     {
525         unsigned __int16 val;
526         details::SafeCastHelper< unsigned __int16, T, E >::Cast( m_int, val );
527         return val;
528     }
529 
__int32()530     operator __int32() const
531     {
532         __int32 val;
533         details::SafeCastHelper< __int32, T, E >::Cast( m_int, val );
534         return val;
535     }
536 
__int32()537     operator unsigned __int32() const
538     {
539         unsigned __int32 val;
540         details::SafeCastHelper< unsigned __int32, T, E >::Cast( m_int, val );
541         return val;
542     }
543 
544     // The compiler knows that int == __int32
545     // but not that long == __int32
546     operator long() const
547     {
548         long val;
549         details::SafeCastHelper< long, T, E >::Cast( m_int, val );
550         return  val;
551     }
552 
553     operator unsigned long() const
554     {
555         unsigned long val;
556         details::SafeCastHelper< unsigned long, T, E >::Cast( m_int, val );
557         return val;
558     }
559 
__int64()560     operator __int64() const
561     {
562         __int64 val;
563         details::SafeCastHelper< __int64, T, E >::Cast( m_int, val );
564         return val;
565     }
566 
__int64()567     operator unsigned __int64() const
568     {
569         unsigned __int64 val;
570         details::SafeCastHelper< unsigned __int64, T, E >::Cast( m_int, val );
571         return val;
572     }
573 
574 #ifdef _NATIVE_WCHAR_T_DEFINED
wchar_t()575     operator wchar_t() const
576     {
577         unsigned __int16 val;
578         details::SafeCastHelper< unsigned __int16, T, E >::Cast( m_int, val );
579         return val;
580     }
581 #endif  /* _NATIVE_WCHAR_T_DEFINED */
582 
583     // If you need a pointer to the data
584     // this could be dangerous, but allows you to correctly pass
585     // instances of this class to APIs that take a pointer to an integer
586     // also see overloaded address-of operator below
Ptr()587     T* Ptr() throw() { return &m_int; }
Ptr()588     const T* Ptr() const throw() { return &m_int; }
Ref()589     const T& Ref() const throw() { return m_int; }
590 
591     // Unary operators
592     bool operator !() const throw() { return (!m_int) ? true : false; }
593 
594     // operator + (unary)
595     // note - normally, the '+' and '-' operators will upcast to a signed int
596     // for T < 32 bits. This class changes behavior to preserve type
597     const SafeInt< T, E >& operator +() const throw() { return *this; };
598 
599     //unary  -
600     SafeInt< T, E > operator -() const
601     {
602         // Note - unsigned still performs the bitwise manipulation
603         // will warn at level 2 or higher if the value is 32-bit or larger
604         T tmp;
605         details::NegationHelper< T, E, details::IntTraits< T >::isSigned >::Negative( m_int, tmp );
606         return SafeInt< T, E >( tmp );
607     }
608 
609     // prefix increment operator
610     SafeInt< T, E >& operator ++()
611     {
612         if( m_int != details::IntTraits< T >::maxInt )
613         {
614             ++m_int;
615             return *this;
616         }
617         E::SafeIntOnOverflow();
618     }
619 
620     // prefix decrement operator
621     SafeInt< T, E >& operator --()
622     {
623         if( m_int != details::IntTraits< T >::minInt )
624         {
625             --m_int;
626             return *this;
627         }
628         E::SafeIntOnOverflow();
629     }
630 
631     // note that postfix operators have inherently worse perf
632     // characteristics
633 
634     // postfix increment operator
635     SafeInt< T, E > operator ++( int ) // dummy arg to comply with spec
636     {
637         if( m_int != details::IntTraits< T >::maxInt )
638         {
639             SafeInt< T, E > tmp( m_int );
640 
641             m_int++;
642             return tmp;
643         }
644         E::SafeIntOnOverflow();
645     }
646 
647     // postfix decrement operator
648     SafeInt< T, E > operator --( int ) // dummy arg to comply with spec
649     {
650         if( m_int != details::IntTraits< T >::minInt )
651         {
652             SafeInt< T, E > tmp( m_int );
653             m_int--;
654             return tmp;
655         }
656         E::SafeIntOnOverflow();
657     }
658 
659     // One's complement
660     // Note - this operator will normally change size to an int
661     // cast in return improves perf and maintains type
662     SafeInt< T, E > operator ~() const throw() { return SafeInt< T, E >( (T)~m_int ); }
663 
664     // Binary operators
665     //
666     // arithmetic binary operators
667     // % modulus
668     // * multiplication
669     // / division
670     // + addition
671     // - subtraction
672     //
673     // For each of the arithmetic operators, you will need to
674     // use them as follows:
675     //
676     // SafeInt<char> c = 2;
677     // SafeInt<int>  i = 3;
678     //
679     // SafeInt<int> i2 = i op (char)c;
680     // OR
681     // SafeInt<char> i2 = (int)i op c;
682     //
683     // The base problem is that if the lhs and rhs inputs are different SafeInt types
684     // it is not possible in this implementation to determine what type of SafeInt
685     // should be returned. You have to let the class know which of the two inputs
686     // need to be the return type by forcing the other value to the base integer type.
687     //
688     // Note - as per feedback from Scott Meyers, I'm exploring how to get around this.
689     // 3.0 update - I'm still thinking about this. It can be done with template metaprogramming,
690     // but it is tricky, and there's a perf vs. correctness tradeoff where the right answer
691     // is situational.
692     //
693     // The case of:
694     //
695     // SafeInt< T, E > i, j, k;
696     // i = j op k;
697     //
698     // works just fine and no unboxing is needed because the return type is not ambiguous.
699 
700     // Modulus
701     // Modulus has some convenient properties -
702     // first, the magnitude of the return can never be
703     // larger than the lhs operand, and it must be the same sign
704     // as well. It does, however, suffer from the same promotion
705     // problems as comparisons, division and other operations
706     template < typename U >
707     SafeInt< T, E > operator %( U rhs ) const
708     {
709         T result;
710         details::ModulusHelper< T, U, E >::Modulus( m_int, rhs, result );
711         return SafeInt< T, E >( result );
712     }
713 
714     SafeInt< T, E > operator %( SafeInt< T, E > rhs ) const
715     {
716         T result;
717         details::ModulusHelper< T, T, E >::Modulus( m_int, rhs, result );
718         return SafeInt< T, E >( result );
719     }
720 
721     // Modulus assignment
722     template < typename U >
723     SafeInt< T, E >& operator %=( U rhs )
724     {
725         details::ModulusHelper< T, U, E >::Modulus( m_int, rhs, m_int );
726         return *this;
727     }
728 
729     template < typename U >
730     SafeInt< T, E >& operator %=( SafeInt< U, E > rhs )
731     {
732         details::ModulusHelper< T, U, E >::Modulus( m_int, (U)rhs, m_int );
733         return *this;
734     }
735 
736     // Multiplication
737     template < typename U >
738     SafeInt< T, E > operator *( U rhs ) const
739     {
740         T ret( 0 );
741         details::MultiplicationHelper< T, U, E >::Multiply( m_int, rhs, ret );
742         return SafeInt< T, E >( ret );
743     }
744 
745     SafeInt< T, E > operator *( SafeInt< T, E > rhs ) const
746     {
747         T ret( 0 );
748         details::MultiplicationHelper< T, T, E >::Multiply( m_int, (T)rhs, ret );
749         return SafeInt< T, E >( ret );
750     }
751 
752     // Multiplication assignment
753     SafeInt< T, E >& operator *=( SafeInt< T, E > rhs )
754     {
755         details::MultiplicationHelper< T, T, E >::Multiply( m_int, (T)rhs, m_int );
756         return *this;
757     }
758 
759     template < typename U >
760     SafeInt< T, E >& operator *=( U rhs )
761     {
762         details::MultiplicationHelper< T, U, E >::Multiply( m_int, rhs, m_int );
763         return *this;
764     }
765 
766     template < typename U >
767     SafeInt< T, E >& operator *=( SafeInt< U, E > rhs )
768     {
769         details::MultiplicationHelper< T, U, E >::Multiply( m_int, rhs.Ref(), m_int );
770         return *this;
771     }
772 
773     // Division
774     template < typename U >
775     SafeInt< T, E > operator /( U rhs ) const
776     {
777         T ret( 0 );
778         details::DivisionHelper< T, U, E >::Divide( m_int, rhs, ret );
779         return SafeInt< T, E >( ret );
780     }
781 
782     SafeInt< T, E > operator /( SafeInt< T, E > rhs ) const
783     {
784         T ret( 0 );
785         details::DivisionHelper< T, T, E >::Divide( m_int, (T)rhs, ret );
786         return SafeInt< T, E >( ret );
787     }
788 
789     // Division assignment
790     SafeInt< T, E >& operator /=( SafeInt< T, E > i )
791     {
792         details::DivisionHelper< T, T, E >::Divide( m_int, (T)i, m_int );
793         return *this;
794     }
795 
796     template < typename U > SafeInt< T, E >& operator /=( U i )
797     {
798         details::DivisionHelper< T, U, E >::Divide( m_int, i, m_int );
799         return *this;
800     }
801 
802     template < typename U > SafeInt< T, E >& operator /=( SafeInt< U, E > i )
803     {
804         details::DivisionHelper< T, U, E >::Divide( m_int, (U)i, m_int );
805         return *this;
806     }
807 
808     // For addition and subtraction
809 
810     // Addition
811     SafeInt< T, E > operator +( SafeInt< T, E > rhs ) const
812     {
813         T ret( 0 );
814         details::AdditionHelper< T, T, E >::Addition( m_int, (T)rhs, ret );
815         return SafeInt< T, E >( ret );
816     }
817 
818     template < typename U >
819     SafeInt< T, E > operator +( U rhs ) const
820     {
821         T ret( 0 );
822         details::AdditionHelper< T, U, E >::Addition( m_int, rhs, ret );
823         return SafeInt< T, E >( ret );
824     }
825 
826     //addition assignment
827     SafeInt< T, E >& operator +=( SafeInt< T, E > rhs )
828     {
829         details::AdditionHelper< T, T, E >::Addition( m_int, (T)rhs, m_int );
830         return *this;
831     }
832 
833     template < typename U >
834     SafeInt< T, E >& operator +=( U rhs )
835     {
836         details::AdditionHelper< T, U, E >::Addition( m_int, rhs, m_int );
837         return *this;
838     }
839 
840     template < typename U >
841     SafeInt< T, E >& operator +=( SafeInt< U, E > rhs )
842     {
843         details::AdditionHelper< T, U, E >::Addition( m_int, (U)rhs, m_int );
844         return *this;
845     }
846 
847     // Subtraction
848     template < typename U >
849     SafeInt< T, E > operator -( U rhs ) const
850     {
851         T ret( 0 );
852         details::SubtractionHelper< T, U, E >::Subtract( m_int, rhs, ret );
853         return SafeInt< T, E >( ret );
854     }
855 
856     SafeInt< T, E > operator -(SafeInt< T, E > rhs) const
857     {
858         T ret( 0 );
859         details::SubtractionHelper< T, T, E >::Subtract( m_int, (T)rhs, ret );
860         return SafeInt< T, E >( ret );
861     }
862 
863     // Subtraction assignment
864     SafeInt< T, E >& operator -=( SafeInt< T, E > rhs )
865     {
866         details::SubtractionHelper< T, T, E >::Subtract( m_int, (T)rhs, m_int );
867         return *this;
868     }
869 
870     template < typename U >
871     SafeInt< T, E >& operator -=( U rhs )
872     {
873         details::SubtractionHelper< T, U, E >::Subtract( m_int, rhs, m_int );
874         return *this;
875     }
876 
877     template < typename U >
878     SafeInt< T, E >& operator -=( SafeInt< U, E > rhs )
879     {
880         details::SubtractionHelper< T, U, E >::Subtract( m_int, (U)rhs, m_int );
881         return *this;
882     }
883 
884     // Comparison operators
885     // Additional overloads defined outside the class
886     // to allow for cases where the SafeInt is the rhs value
887 
888     // Less than
889     template < typename U >
890     bool operator <( U rhs ) const throw()
891     {
892         return details::GreaterThanTest< U, T >::GreaterThan( rhs, m_int );
893     }
894 
895     bool operator <( SafeInt< T, E > rhs ) const throw()
896     {
897         return m_int < (T)rhs;
898     }
899 
900     // Greater than or eq.
901     template < typename U >
throw()902     bool operator >=( U rhs ) const throw()
903     {
904         return !details::GreaterThanTest< U, T >::GreaterThan( rhs, m_int );
905     }
906 
throw()907     bool operator >=( SafeInt< T, E > rhs ) const throw()
908     {
909         return m_int >= (T)rhs;
910     }
911 
912     // Greater than
913     template < typename U >
throw()914     bool operator >( U rhs ) const throw()
915     {
916         return details::GreaterThanTest< T, U >::GreaterThan( m_int, rhs );
917     }
918 
throw()919     bool operator >( SafeInt< T, E > rhs ) const throw()
920     {
921         return m_int > (T)rhs;
922     }
923 
924     // Less than or eq.
925     template < typename U >
926     bool operator <=( U rhs ) const throw()
927     {
928         return !details::GreaterThanTest< T, U >::GreaterThan( m_int, rhs );
929     }
930 
931     bool operator <=( SafeInt< T, E > rhs ) const throw()
932     {
933         return m_int <= (T)rhs;
934     }
935 
936     // Equality
937     template < typename U >
938     bool operator ==( U rhs ) const throw()
939     {
940         return details::EqualityTest< T, U >::IsEquals( m_int, rhs );
941     }
942 
943     // Need an explicit override for type bool
944     bool operator ==( bool rhs ) const throw()
945     {
946         return ( m_int == 0 ? false : true ) == rhs;
947     }
948 
949     bool operator ==( SafeInt< T, E > rhs ) const throw() { return m_int == (T)rhs; }
950 
951     // != operators
952     template < typename U >
953     bool operator !=( U rhs ) const throw()
954     {
955         return !details::EqualityTest< T, U >::IsEquals( m_int, rhs );
956     }
957 
958     bool operator !=( bool b ) const throw()
959     {
960         return ( m_int == 0 ? false : true ) != b;
961     }
962 
963     bool operator !=( SafeInt< T, E > rhs ) const throw() { return m_int != (T)rhs; }
964 
965     // Shift operators
966     // Note - shift operators ALWAYS return the same type as the lhs
967     // specific version for SafeInt< T, E > not needed -
968     // code path is exactly the same as for SafeInt< U, E > as rhs
969 
970     // Left shift
971     // Also, shifting > bitcount is undefined - trap in debug (check _SAFEINT_SHIFT_ASSERT)
972 
973     template < typename U >
974     SafeInt< T, E > operator <<( U bits ) const throw()
975     {
976         _SAFEINT_SHIFT_ASSERT( !details::IntTraits< U >::isSigned || bits >= 0 );
977         _SAFEINT_SHIFT_ASSERT( bits < (int)details::IntTraits< T >::bitCount );
978 
979         return SafeInt< T, E >( (T)( m_int << bits ) );
980     }
981 
982     template < typename U >
983     SafeInt< T, E > operator <<( SafeInt< U, E > bits ) const throw()
984     {
985         _SAFEINT_SHIFT_ASSERT( !details::IntTraits< U >::isSigned || (U)bits >= 0 );
986         _SAFEINT_SHIFT_ASSERT( (U)bits < (int)details::IntTraits< T >::bitCount );
987 
988         return SafeInt< T, E >( (T)( m_int << (U)bits ) );
989     }
990 
991     // Left shift assignment
992 
993     template < typename U >
994     SafeInt< T, E >& operator <<=( U bits ) throw()
995     {
996         _SAFEINT_SHIFT_ASSERT( !details::IntTraits< U >::isSigned || bits >= 0 );
997         _SAFEINT_SHIFT_ASSERT( bits < (int)details::IntTraits< T >::bitCount );
998 
999         m_int <<= bits;
1000         return *this;
1001     }
1002 
1003     template < typename U >
1004     SafeInt< T, E >& operator <<=( SafeInt< U, E > bits ) throw()
1005     {
1006         _SAFEINT_SHIFT_ASSERT( !details::IntTraits< U >::isSigned || (U)bits >= 0 );
1007         _SAFEINT_SHIFT_ASSERT( (U)bits < (int)details::IntTraits< T >::bitCount );
1008 
1009         m_int <<= (U)bits;
1010         return *this;
1011     }
1012 
1013     // Right shift
1014     template < typename U >
throw()1015     SafeInt< T, E > operator >>( U bits ) const throw()
1016     {
1017         _SAFEINT_SHIFT_ASSERT( !details::IntTraits< U >::isSigned || bits >= 0 );
1018         _SAFEINT_SHIFT_ASSERT( bits < (int)details::IntTraits< T >::bitCount );
1019 
1020         return SafeInt< T, E >( (T)( m_int >> bits ) );
1021     }
1022 
1023     template < typename U >
throw()1024     SafeInt< T, E > operator >>( SafeInt< U, E > bits ) const throw()
1025     {
1026         _SAFEINT_SHIFT_ASSERT( !details::IntTraits< U >::isSigned || (U)bits >= 0 );
1027         _SAFEINT_SHIFT_ASSERT( bits < (int)details::IntTraits< T >::bitCount );
1028 
1029         return SafeInt< T, E >( (T)(m_int >> (U)bits) );
1030     }
1031 
1032     // Right shift assignment
1033     template < typename U >
throw()1034     SafeInt< T, E >& operator >>=( U bits ) throw()
1035     {
1036         _SAFEINT_SHIFT_ASSERT( !details::IntTraits< U >::isSigned || bits >= 0 );
1037         _SAFEINT_SHIFT_ASSERT( bits < (int)details::IntTraits< T >::bitCount );
1038 
1039         m_int >>= bits;
1040         return *this;
1041     }
1042 
1043     template < typename U >
throw()1044     SafeInt< T, E >& operator >>=( SafeInt< U, E > bits ) throw()
1045     {
1046         _SAFEINT_SHIFT_ASSERT( !details::IntTraits< U >::isSigned || (U)bits >= 0 );
1047         _SAFEINT_SHIFT_ASSERT( (U)bits < (int)details::IntTraits< T >::bitCount );
1048 
1049         m_int >>= (U)bits;
1050         return *this;
1051     }
1052 
1053     // Bitwise operators
1054     // This only makes sense if we're dealing with the same type and size
1055     // demand a type T, or something that fits into a type T
1056 
1057     // Bitwise &
throw()1058     SafeInt< T, E > operator &( SafeInt< T, E > rhs ) const throw()
1059     {
1060         return SafeInt< T, E >( m_int & (T)rhs );
1061     }
1062 
1063     template < typename U >
throw()1064     SafeInt< T, E > operator &( U rhs ) const throw()
1065     {
1066         // we want to avoid setting bits by surprise
1067         // consider the case of lhs = int, value = 0xffffffff
1068         //                      rhs = char, value = 0xff
1069         //
1070         // programmer intent is to get only the lower 8 bits
1071         // normal behavior is to upcast both sides to an int
1072         // which then sign extends rhs, setting all the bits
1073 
1074         // If you land in the assert, this is because the bitwise operator
1075         // was causing unexpected behavior. Fix is to properly cast your inputs
1076         // so that it works like you meant, not unexpectedly
1077 
1078         return SafeInt< T, E >( details::BinaryAndHelper< T, U >::And( m_int, rhs ) );
1079     }
1080 
1081     // Bitwise & assignment
throw()1082     SafeInt< T, E >& operator &=( SafeInt< T, E > rhs ) throw()
1083     {
1084         m_int &= (T)rhs;
1085         return *this;
1086     }
1087 
1088     template < typename U >
throw()1089     SafeInt< T, E >& operator &=( U rhs ) throw()
1090     {
1091         m_int = details::BinaryAndHelper< T, U >::And( m_int, rhs );
1092         return *this;
1093     }
1094 
1095     template < typename U >
throw()1096     SafeInt< T, E >& operator &=( SafeInt< U, E > rhs ) throw()
1097     {
1098         m_int = details::BinaryAndHelper< T, U >::And( m_int, (U)rhs );
1099         return *this;
1100     }
1101 
1102     // XOR
1103     SafeInt< T, E > operator ^( SafeInt< T, E > rhs ) const throw()
1104     {
1105         return SafeInt< T, E >( (T)( m_int ^ (T)rhs ) );
1106     }
1107 
1108     template < typename U >
1109     SafeInt< T, E > operator ^( U rhs ) const throw()
1110     {
1111         // If you land in the assert, this is because the bitwise operator
1112         // was causing unexpected behavior. Fix is to properly cast your inputs
1113         // so that it works like you meant, not unexpectedly
1114 
1115         return SafeInt< T, E >( details::BinaryXorHelper< T, U >::Xor( m_int, rhs ) );
1116     }
1117 
1118     // XOR assignment
1119     SafeInt< T, E >& operator ^=( SafeInt< T, E > rhs ) throw()
1120     {
1121         m_int ^= (T)rhs;
1122         return *this;
1123     }
1124 
1125     template < typename U >
1126     SafeInt< T, E >& operator ^=( U rhs ) throw()
1127     {
1128         m_int = details::BinaryXorHelper< T, U >::Xor( m_int, rhs );
1129         return *this;
1130     }
1131 
1132     template < typename U >
1133     SafeInt< T, E >& operator ^=( SafeInt< U, E > rhs ) throw()
1134     {
1135         m_int = details::BinaryXorHelper< T, U >::Xor( m_int, (U)rhs );
1136         return *this;
1137     }
1138 
1139     // bitwise OR
1140     SafeInt< T, E > operator |( SafeInt< T, E > rhs ) const throw()
1141     {
1142         return SafeInt< T, E >( (T)( m_int | (T)rhs ) );
1143     }
1144 
1145     template < typename U >
1146     SafeInt< T, E > operator |( U rhs ) const throw()
1147     {
1148         return SafeInt< T, E >( details::BinaryOrHelper< T, U >::Or( m_int, rhs ) );
1149     }
1150 
1151     // bitwise OR assignment
1152     SafeInt< T, E >& operator |=( SafeInt< T, E > rhs ) throw()
1153     {
1154         m_int |= (T)rhs;
1155         return *this;
1156     }
1157 
1158     template < typename U >
1159     SafeInt< T, E >& operator |=( U rhs ) throw()
1160     {
1161         m_int = details::BinaryOrHelper< T, U >::Or( m_int, rhs );
1162         return *this;
1163     }
1164 
1165     template < typename U >
1166     SafeInt< T, E >& operator |=( SafeInt< U, E > rhs ) throw()
1167     {
1168         m_int = details::BinaryOrHelper< T, U >::Or( m_int, (U)rhs );
1169         return *this;
1170     }
1171 
1172     // Miscellaneous helper functions
throw()1173     SafeInt< T, E > Min( SafeInt< T, E > test, SafeInt< T, E > floor = SafeInt< T, E >( details::IntTraits< T >::minInt ) ) const throw()
1174     {
1175         T tmp = test < m_int ? test : m_int;
1176         return tmp < floor ? floor : tmp;
1177     }
1178 
throw()1179     SafeInt< T, E > Max( SafeInt< T, E > test, SafeInt< T, E > upper = SafeInt< T, E >( details::IntTraits< T >::maxInt ) ) const throw()
1180     {
1181         T tmp = test > m_int ? test : m_int;
1182         return tmp > upper ? upper : tmp;
1183     }
1184 
Swap(SafeInt<T,E> & with)1185     void Swap( SafeInt< T, E >& with ) throw()
1186     {
1187         T temp( m_int );
1188         m_int = with.m_int;
1189         with.m_int = temp;
1190     }
1191 
1192     template < int bits >
Align()1193     const SafeInt< T, E >& Align()
1194     {
1195         // Zero is always aligned
1196         if( m_int == 0 )
1197             return *this;
1198 
1199         // We don't support aligning negative numbers at this time
1200         // Can't align unsigned numbers on bitCount (e.g., 8 bits = 256, unsigned char max = 255)
1201         // or signed numbers on bitCount-1 (e.g., 7 bits = 128, signed char max = 127).
1202         // Also makes no sense to try to align on negative or no bits.
1203 
1204         _SAFEINT_SHIFT_ASSERT( ( ( details::IntTraits<T>::isSigned && bits < (int)details::IntTraits< T >::bitCount - 1 )
1205             || ( !details::IntTraits<T>::isSigned && bits < (int)details::IntTraits< T >::bitCount ) ) &&
1206             bits >= 0 && ( !details::IntTraits<T>::isSigned || m_int > 0 ) );
1207 
1208         const T AlignValue = ( (T)1 << bits ) - 1;
1209 
1210         m_int = ( m_int + AlignValue ) & ~AlignValue;
1211 
1212         if( m_int <= 0 )
1213             E::SafeIntOnOverflow();
1214 
1215         return *this;
1216     }
1217 
1218     // Commonly needed alignments:
Align2()1219     const SafeInt< T, E >& Align2()  { return Align< 1 >(); }
Align4()1220     const SafeInt< T, E >& Align4()  { return Align< 2 >(); }
Align8()1221     const SafeInt< T, E >& Align8()  { return Align< 3 >(); }
Align16()1222     const SafeInt< T, E >& Align16() { return Align< 4 >(); }
Align32()1223     const SafeInt< T, E >& Align32() { return Align< 5 >(); }
Align64()1224     const SafeInt< T, E >& Align64() { return Align< 6 >(); }
1225 
1226 private:
1227     T m_int;
1228 };
1229 
1230 // Externally defined functions for the case of U op SafeInt< T, E >
1231 template < typename T, typename U, typename E >
1232 bool operator <( U lhs, SafeInt< T, E > rhs ) throw()
1233 {
1234     return details::GreaterThanTest< T, U >::GreaterThan( (T)rhs, lhs );
1235 }
1236 
1237 template < typename T, typename U, typename E >
1238 bool operator <( SafeInt< U, E > lhs, SafeInt< T, E > rhs ) throw()
1239 {
1240     return details::GreaterThanTest< T, U >::GreaterThan( (T)rhs, (U)lhs );
1241 }
1242 
1243 // Greater than
1244 template < typename T, typename U, typename E >
throw()1245 bool operator >( U lhs, SafeInt< T, E > rhs ) throw()
1246 {
1247     return details::GreaterThanTest< U, T >::GreaterThan( lhs, (T)rhs );
1248 }
1249 
1250 template < typename T, typename U, typename E >
throw()1251 bool operator >( SafeInt< T, E > lhs, SafeInt< U, E > rhs ) throw()
1252 {
1253     return details::GreaterThanTest< T, U >::GreaterThan( (T)lhs, (U)rhs );
1254 }
1255 
1256 // Greater than or equal
1257 template < typename T, typename U, typename E >
throw()1258 bool operator >=( U lhs, SafeInt< T, E > rhs ) throw()
1259 {
1260     return !details::GreaterThanTest< T, U >::GreaterThan( (T)rhs, lhs );
1261 }
1262 
1263 template < typename T, typename U, typename E >
throw()1264 bool operator >=( SafeInt< T, E > lhs, SafeInt< U, E > rhs ) throw()
1265 {
1266     return !details::GreaterThanTest< U, T >::GreaterThan( (U)rhs, (T)lhs );
1267 }
1268 
1269 // Less than or equal
1270 template < typename T, typename U, typename E >
1271 bool operator <=( U lhs, SafeInt< T, E > rhs ) throw()
1272 {
1273     return !details::GreaterThanTest< U, T >::GreaterThan( lhs, (T)rhs );
1274 }
1275 
1276 template < typename T, typename U, typename E >
1277 bool operator <=( SafeInt< T, E > lhs, SafeInt< U, E > rhs ) throw()
1278 {
1279     return !details::GreaterThanTest< T, U >::GreaterThan( (T)lhs, (U)rhs );
1280 }
1281 
1282 // equality
1283 // explicit overload for bool
1284 template < typename T, typename E >
1285 bool operator ==( bool lhs, SafeInt< T, E > rhs ) throw()
1286 {
1287     return lhs == ( (T)rhs == 0 ? false : true );
1288 }
1289 
1290 template < typename T, typename U, typename E >
1291 bool operator ==( U lhs, SafeInt< T, E > rhs ) throw()
1292 {
1293     return details::EqualityTest< T, U >::IsEquals((T)rhs, lhs);
1294 }
1295 
1296 template < typename T, typename U, typename E >
1297 bool operator ==( SafeInt< T, E > lhs, SafeInt< U, E > rhs ) throw()
1298 {
1299     return details::EqualityTest< T, U >::IsEquals( (T)lhs, (U)rhs );
1300 }
1301 
1302 //not equals
1303 template < typename T, typename U, typename E >
1304 bool operator !=( U lhs, SafeInt< T, E > rhs ) throw()
1305 {
1306     return !details::EqualityTest< T, U >::IsEquals( rhs, lhs );
1307 }
1308 
1309 template < typename T, typename E >
1310 bool operator !=( bool lhs, SafeInt< T, E > rhs ) throw()
1311 {
1312     return ( (T)rhs == 0 ? false : true ) != lhs;
1313 }
1314 
1315 template < typename T, typename U, typename E >
1316 bool operator !=( SafeInt< T, E > lhs, SafeInt< U, E > rhs ) throw()
1317 {
1318     return !details::EqualityTest< T, U >::IsEquals( lhs, rhs );
1319 }
1320 
1321 // Modulus
1322 template < typename T, typename U, typename E >
1323 SafeInt< T, E > operator %( U lhs, SafeInt< T, E > rhs )
1324 {
1325     // Value of return depends on sign of lhs
1326     // This one may not be safe - bounds check in constructor
1327     // if lhs is negative and rhs is unsigned, this will throw an exception.
1328 
1329     // Fast-track the simple case
1330     // same size and same sign
1331 #pragma warning(suppress:4127 6326)
1332     if( sizeof(T) == sizeof(U) && details::IntTraits< T >::isSigned == details::IntTraits< U >::isSigned )
1333     {
1334         if( rhs != 0 )
1335         {
1336             if( details::IntTraits< T >::isSigned && (T)rhs == -1 )
1337                 return 0;
1338 
1339             return SafeInt< T, E >( (T)( lhs % (T)rhs ) );
1340         }
1341 
1342         E::SafeIntOnDivZero();
1343     }
1344 
1345     return SafeInt< T, E >( ( SafeInt< U, E >( lhs ) % (T)rhs ) );
1346 }
1347 
1348 // Multiplication
1349 template < typename T, typename U, typename E >
1350 SafeInt< T, E > operator *( U lhs, SafeInt< T, E > rhs )
1351 {
1352     T ret( 0 );
1353     details::MultiplicationHelper< T, U, E >::Multiply( (T)rhs, lhs, ret );
1354     return SafeInt< T, E >(ret);
1355 }
1356 
1357 // Division
1358 template < typename T, typename U, typename E > SafeInt< T, E > operator /( U lhs, SafeInt< T, E > rhs )
1359 {
1360 #pragma warning(push)
1361 #pragma warning(disable: 4127 4146 4307 4310 6326)
1362     // Corner case - has to be handled separately
1363     if( details::DivisionMethod< U, T >::method ==  details::DivisionState_UnsignedSigned )
1364     {
1365         if( (T)rhs > 0 )
1366             return SafeInt< T, E >( lhs/(T)rhs );
1367 
1368         // Now rhs is either negative, or zero
1369         if( (T)rhs != 0 )
1370         {
1371             if( sizeof( U ) >= 4 && sizeof( T ) <= sizeof( U ) )
1372             {
1373                 // Problem case - normal casting behavior changes meaning
1374                 // flip rhs to positive
1375                 // any operator casts now do the right thing
1376                 U tmp;
1377                 if( sizeof(T) == 4 )
1378                     tmp = lhs/(U)(unsigned __int32)( -(T)rhs );
1379                 else
1380                     tmp = lhs/(U)( -(T)rhs );
1381 
1382                 if( tmp <= details::IntTraits< T >::maxInt )
1383                     return SafeInt< T, E >( -( (T)tmp ) );
1384 
1385                 // Corner case
1386                 // Note - this warning happens because we're not using partial
1387                 // template specialization in this case. For any real cases where
1388                 // this block isn't optimized out, the warning won't be present.
1389                 if( tmp == (U)details::IntTraits< T >::maxInt + 1 )
1390                     return SafeInt< T, E >( details::IntTraits< T >::minInt );
1391 
1392                 E::SafeIntOnOverflow();
1393             }
1394 
1395             return SafeInt< T, E >(lhs/(T)rhs);
1396         }
1397 
1398         E::SafeIntOnDivZero();
1399     } // method == DivisionState_UnsignedSigned
1400 
1401     if( details::SafeIntCompare< T, U >::isBothSigned )
1402     {
1403         if( lhs == details::IntTraits< U >::minInt && (T)rhs == -1 )
1404         {
1405             // corner case of a corner case - lhs = min int, rhs = -1,
1406             // but rhs is the return type, so in essence, we can return -lhs
1407             // if rhs is a larger type than lhs
1408             if( sizeof( U ) < sizeof( T ) )
1409             {
1410                 return SafeInt< T, E >( (T)( -(T)details::IntTraits< U >::minInt ) );
1411             }
1412 
1413             // If rhs is smaller or the same size int, then -minInt won't work
1414             E::SafeIntOnOverflow();
1415         }
1416     }
1417 
1418     // Otherwise normal logic works with addition of bounds check when casting from U->T
1419     U ret;
1420     details::DivisionHelper< U, T, E >::Divide( lhs, (T)rhs, ret );
1421     return SafeInt< T, E >( ret );
1422 #pragma warning(pop)
1423 }
1424 
1425 // Addition
1426 template < typename T, typename U, typename E >
1427 SafeInt< T, E > operator +( U lhs, SafeInt< T, E > rhs )
1428 {
1429     T ret( 0 );
1430     details::AdditionHelper< T, U, E >::Addition( (T)rhs, lhs, ret );
1431     return SafeInt< T, E >( ret );
1432 }
1433 
1434 // Subtraction
1435 template < typename T, typename U, typename E >
1436 SafeInt< T, E > operator -( U lhs, SafeInt< T, E > rhs )
1437 {
1438     T ret( 0 );
1439     details::SubtractionHelper< U, T, E, details::SubtractionMethod2< U, T >::method >::Subtract( lhs, rhs.Ref(), ret );
1440 
1441     return SafeInt< T, E >( ret );
1442 }
1443 
1444 // Overrides designed to deal with cases where a SafeInt is assigned out
1445 // to a normal int - this at least makes the last operation safe
1446 // +=
1447 template < typename T, typename U, typename E >
1448 T& operator +=( T& lhs, SafeInt< U, E > rhs )
1449 {
1450     T ret( 0 );
1451     details::AdditionHelper< T, U, E >::Addition( lhs, (U)rhs, ret );
1452     lhs = ret;
1453     return lhs;
1454 }
1455 
1456 template < typename T, typename U, typename E >
1457 T& operator -=( T& lhs, SafeInt< U, E > rhs )
1458 {
1459     T ret( 0 );
1460     details::SubtractionHelper< T, U, E >::Subtract( lhs, (U)rhs, ret );
1461     lhs = ret;
1462     return lhs;
1463 }
1464 
1465 template < typename T, typename U, typename E >
1466 T& operator *=( T& lhs, SafeInt< U, E > rhs )
1467 {
1468     T ret( 0 );
1469     details::MultiplicationHelper< T, U, E >::Multiply( lhs, (U)rhs, ret );
1470     lhs = ret;
1471     return lhs;
1472 }
1473 
1474 template < typename T, typename U, typename E >
1475 T& operator /=( T& lhs, SafeInt< U, E > rhs )
1476 {
1477     T ret( 0 );
1478     details::DivisionHelper< T, U, E >::Divide( lhs, (U)rhs, ret );
1479     lhs = ret;
1480     return lhs;
1481 }
1482 
1483 template < typename T, typename U, typename E >
1484 T& operator %=( T& lhs, SafeInt< U, E > rhs )
1485 {
1486     T ret( 0 );
1487     details::ModulusHelper< T, U, E >::Modulus( lhs, (U)rhs, ret );
1488     lhs = ret;
1489     return lhs;
1490 }
1491 
1492 template < typename T, typename U, typename E >
throw()1493 T& operator &=( T& lhs, SafeInt< U, E > rhs ) throw()
1494 {
1495     lhs = details::BinaryAndHelper< T, U >::And( lhs, (U)rhs );
1496     return lhs;
1497 }
1498 
1499 template < typename T, typename U, typename E >
1500 T& operator ^=( T& lhs, SafeInt< U, E > rhs ) throw()
1501 {
1502     lhs = details::BinaryXorHelper< T, U >::Xor( lhs, (U)rhs );
1503     return lhs;
1504 }
1505 
1506 template < typename T, typename U, typename E >
1507 T& operator |=( T& lhs, SafeInt< U, E > rhs ) throw()
1508 {
1509     lhs = details::BinaryOrHelper< T, U >::Or( lhs, (U)rhs );
1510     return lhs;
1511 }
1512 
1513 template < typename T, typename U, typename E >
1514 T& operator <<=( T& lhs, SafeInt< U, E > rhs ) throw()
1515 {
1516     lhs = (T)( SafeInt< T, E >( lhs ) << (U)rhs );
1517     return lhs;
1518 }
1519 
1520 template < typename T, typename U, typename E >
throw()1521 T& operator >>=( T& lhs, SafeInt< U, E > rhs ) throw()
1522 {
1523     lhs = (T)( SafeInt< T, E >( lhs ) >> (U)rhs );
1524     return lhs;
1525 }
1526 
1527 // Specific pointer overrides
1528 // Note - this function makes no attempt to ensure
1529 // that the resulting pointer is still in the buffer, only
1530 // that no int overflows happened on the way to getting the new pointer
1531 template < typename T, typename U, typename E >
1532 T*& operator +=( T*& lhs, SafeInt< U, E > rhs )
1533 {
1534     // Cast the pointer to a number so we can do arithmetic
1535     SafeInt< uintptr_t, E > ptr_val = reinterpret_cast< uintptr_t >( lhs );
1536     // Check first that rhs is valid for the type of ptrdiff_t
1537     // and that multiplying by sizeof( T ) doesn't overflow a ptrdiff_t
1538     // Next, we need to add 2 SafeInts of different types, so unbox the ptr_diff
1539     // Finally, cast the number back to a pointer of the correct type
1540     lhs = reinterpret_cast< T* >( (uintptr_t)( ptr_val + (ptrdiff_t)( SafeInt< ptrdiff_t, E >( rhs ) * sizeof( T ) ) ) );
1541     return lhs;
1542 }
1543 
1544 template < typename T, typename U, typename E >
1545 T*& operator -=( T*& lhs, SafeInt< U, E > rhs )
1546 {
1547     // Cast the pointer to a number so we can do arithmetic
1548     SafeInt< size_t, E > ptr_val = reinterpret_cast< uintptr_t >( lhs );
1549     // See above for comments
1550     lhs = reinterpret_cast< T* >( (uintptr_t)( ptr_val - (ptrdiff_t)( SafeInt< ptrdiff_t, E >( rhs ) * sizeof( T ) ) ) );
1551     return lhs;
1552 }
1553 
1554 template < typename T, typename U, typename E >
1555 T*& operator *=( T* lhs, SafeInt< U, E >)
1556 {
1557     static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1558     return lhs;
1559 }
1560 
1561 template < typename T, typename U, typename E >
1562 T*& operator /=( T* lhs, SafeInt< U, E >)
1563 {
1564     static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1565     return lhs;
1566 }
1567 
1568 template < typename T, typename U, typename E >
1569 T*& operator %=( T* lhs, SafeInt< U, E >)
1570 {
1571     static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1572     return lhs;
1573 }
1574 
1575 template < typename T, typename U, typename E >
1576 T*& operator &=( T* lhs, SafeInt< U, E >)
1577 {
1578     static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1579     return lhs;
1580 }
1581 
1582 template < typename T, typename U, typename E >
1583 T*& operator ^=( T* lhs, SafeInt< U, E >)
1584 {
1585     static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1586     return lhs;
1587 }
1588 
1589 template < typename T, typename U, typename E >
1590 T*& operator |=( T* lhs, SafeInt< U, E >)
1591 {
1592     static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1593     return lhs;
1594 }
1595 
1596 template < typename T, typename U, typename E >
1597 T*& operator <<=( T* lhs, SafeInt< U, E >)
1598 {
1599     static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1600     return lhs;
1601 }
1602 
1603 template < typename T, typename U, typename E >
1604 T*& operator >>=( T* lhs, SafeInt< U, E >)
1605 {
1606     static_assert( details::DependentFalse< T >::value, "SafeInt<T>: This operator explicitly not supported" );
1607     return lhs;
1608 }
1609 
1610 // Shift operators
1611 // NOTE - shift operators always return the type of the lhs argument
1612 
1613 // Left shift
1614 template < typename T, typename U, typename E >
1615 SafeInt< U, E > operator <<( U lhs, SafeInt< T, E > bits ) throw()
1616 {
1617     _SAFEINT_SHIFT_ASSERT( !details::IntTraits< T >::isSigned || (T)bits >= 0 );
1618     _SAFEINT_SHIFT_ASSERT( (T)bits < (int)details::IntTraits< U >::bitCount );
1619 
1620     return SafeInt< U, E >( (U)( lhs << (T)bits ) );
1621 }
1622 
1623 // Right shift
1624 template < typename T, typename U, typename E >
throw()1625 SafeInt< U, E > operator >>( U lhs, SafeInt< T, E > bits ) throw()
1626 {
1627     _SAFEINT_SHIFT_ASSERT( !details::IntTraits< T >::isSigned || (T)bits >= 0 );
1628     _SAFEINT_SHIFT_ASSERT( (T)bits < (int)details::IntTraits< U >::bitCount );
1629 
1630     return SafeInt< U, E >( (U)( lhs >> (T)bits ) );
1631 }
1632 
1633 // Bitwise operators
1634 // This only makes sense if we're dealing with the same type and size
1635 // demand a type T, or something that fits into a type T.
1636 
1637 // Bitwise &
1638 template < typename T, typename U, typename E >
throw()1639 SafeInt< T, E > operator &( U lhs, SafeInt< T, E > rhs ) throw()
1640 {
1641     return SafeInt< T, E >( details::BinaryAndHelper< T, U >::And( (T)rhs, lhs ) );
1642 }
1643 
1644 // Bitwise XOR
1645 template < typename T, typename U, typename E >
1646 SafeInt< T, E > operator ^( U lhs, SafeInt< T, E > rhs ) throw()
1647 {
1648     return SafeInt< T, E >(details::BinaryXorHelper< T, U >::Xor( (T)rhs, lhs ) );
1649 }
1650 
1651 // Bitwise OR
1652 template < typename T, typename U, typename E >
1653 SafeInt< T, E > operator |( U lhs, SafeInt< T, E > rhs ) throw()
1654 {
1655     return SafeInt< T, E >( details::BinaryOrHelper< T, U >::Or( (T)rhs, lhs ) );
1656 }
1657 
1658 } // namespace utilities
1659 
1660 } // namespace msl
1661 
1662 #pragma pack(pop)
1663 
1664 #pragma warning(pop) // Disable /Wall warnings
1665 #endif // RC_INVOKED
1666