1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef PDFIUM_THIRD_PARTY_BASE_NUMERICS_SAFE_MATH_H_
6 #define PDFIUM_THIRD_PARTY_BASE_NUMERICS_SAFE_MATH_H_
7 
8 #include <stddef.h>
9 
10 #include <limits>
11 #include <type_traits>
12 
13 #include "third_party/base/numerics/safe_math_impl.h"
14 
15 namespace pdfium {
16 namespace base {
17 namespace internal {
18 
19 // CheckedNumeric<> implements all the logic and operators for detecting integer
20 // boundary conditions such as overflow, underflow, and invalid conversions.
21 // The CheckedNumeric type implicitly converts from floating point and integer
22 // data types, and contains overloads for basic arithmetic operations (i.e.: +,
23 // -, *, / for all types and %, <<, >>, &, |, ^ for integers). Type promotions
24 // are a slightly modified version of the standard C arithmetic rules with the
25 // two differences being that there is no default promotion to int and bitwise
26 // logical operations always return an unsigned of the wider type.
27 //
28 // You may also use one of the variadic convenience functions, which accept
29 // standard arithmetic or CheckedNumeric types, perform arithmetic operations,
30 // and return a CheckedNumeric result. The supported functions are:
31 //  CheckAdd() - Addition.
32 //  CheckSub() - Subtraction.
33 //  CheckMul() - Multiplication.
34 //  CheckDiv() - Division.
35 //  CheckMod() - Modulous (integer only).
36 //  CheckLsh() - Left integer shift (integer only).
37 //  CheckRsh() - Right integer shift (integer only).
38 //  CheckAnd() - Bitwise AND (integer only with unsigned result).
39 //  CheckOr()  - Bitwise OR (integer only with unsigned result).
40 //  CheckXor() - Bitwise XOR (integer only with unsigned result).
41 //  CheckMax() - Maximum of supplied arguments.
42 //  CheckMin() - Minimum of supplied arguments.
43 //
44 // The unary negation, increment, and decrement operators are supported, along
45 // with the following unary arithmetic methods, which return a new
46 // CheckedNumeric as a result of the operation:
47 //  Abs() - Absolute value.
48 //  UnsignedAbs() - Absolute value as an equal-width unsigned underlying type
49 //          (valid for only integral types).
50 //  Max() - Returns whichever is greater of the current instance or argument.
51 //          The underlying return type is whichever has the greatest magnitude.
52 //  Min() - Returns whichever is lowest of the current instance or argument.
53 //          The underlying return type is whichever has can represent the lowest
54 //          number in the smallest width (e.g. int8_t over unsigned, int over
55 //          int8_t, and float over int).
56 //
57 // The following methods convert from CheckedNumeric to standard numeric values:
58 //  AssignIfValid() - Assigns the underlying value to the supplied destination
59 //          pointer if the value is currently valid and within the range
60 //          supported by the destination type. Returns true on success.
61 //  ****************************************************************************
62 //  *  WARNING: All of the following functions return a StrictNumeric, which   *
63 //  *  is valid for comparison and assignment operations, but will trigger a   *
64 //  *  compile failure on attempts to assign to a type of insufficient range.  *
65 //  ****************************************************************************
66 //  IsValid() - Returns true if the underlying numeric value is valid (i.e. has
67 //          has not wrapped and is not the result of an invalid conversion).
68 //  ValueOrDie() - Returns the underlying value. If the state is not valid this
69 //          call will crash on a CHECK.
70 //  ValueOrDefault() - Returns the current value, or the supplied default if the
71 //          state is not valid (will not trigger a CHECK).
72 //
73 // The following wrapper functions can be used to avoid the template
74 // disambiguator syntax when converting a destination type.
75 //   IsValidForType<>() in place of: a.template IsValid<Dst>()
76 //   ValueOrDieForType<>() in place of: a.template ValueOrDie()
77 //   ValueOrDefaultForType<>() in place of: a.template ValueOrDefault(default)
78 //
79 // The following are general utility methods that are useful for converting
80 // between arithmetic types and CheckedNumeric types:
81 //  CheckedNumeric::Cast<Dst>() - Instance method returning a CheckedNumeric
82 //          derived from casting the current instance to a CheckedNumeric of
83 //          the supplied destination type.
84 //  MakeCheckedNum() - Creates a new CheckedNumeric from the underlying type of
85 //          the supplied arithmetic, CheckedNumeric, or StrictNumeric type.
86 //
87 // Comparison operations are explicitly not supported because they could result
88 // in a crash on an unexpected CHECK condition. You should use patterns like the
89 // following for comparisons:
90 //   CheckedNumeric<size_t> checked_size = untrusted_input_value;
91 //   checked_size += HEADER LENGTH;
92 //   if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size)
93 //     Do stuff...
94 
95 template <typename T>
96 class CheckedNumeric {
97   static_assert(std::is_arithmetic<T>::value,
98                 "CheckedNumeric<T>: T must be a numeric type.");
99 
100  public:
101   using type = T;
102 
103   constexpr CheckedNumeric() = default;
104 
105   // Copy constructor.
106   template <typename Src>
CheckedNumeric(const CheckedNumeric<Src> & rhs)107   constexpr CheckedNumeric(const CheckedNumeric<Src>& rhs)
108       : state_(rhs.state_.value(), rhs.IsValid()) {}
109 
110   template <typename Src>
111   friend class CheckedNumeric;
112 
113   // This is not an explicit constructor because we implicitly upgrade regular
114   // numerics to CheckedNumerics to make them easier to use.
115   template <typename Src>
CheckedNumeric(Src value)116   constexpr CheckedNumeric(Src value)  // NOLINT(runtime/explicit)
117       : state_(value) {
118     static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric.");
119   }
120 
121   // This is not an explicit constructor because we want a seamless conversion
122   // from StrictNumeric types.
123   template <typename Src>
CheckedNumeric(StrictNumeric<Src> value)124   constexpr CheckedNumeric(
125       StrictNumeric<Src> value)  // NOLINT(runtime/explicit)
126       : state_(static_cast<Src>(value)) {}
127 
128   // IsValid() - The public API to test if a CheckedNumeric is currently valid.
129   // A range checked destination type can be supplied using the Dst template
130   // parameter.
131   template <typename Dst = T>
IsValid()132   constexpr bool IsValid() const {
133     return state_.is_valid() &&
134            IsValueInRangeForNumericType<Dst>(state_.value());
135   }
136 
137   // AssignIfValid(Dst) - Assigns the underlying value if it is currently valid
138   // and is within the range supported by the destination type. Returns true if
139   // successful and false otherwise.
140   template <typename Dst>
AssignIfValid(Dst * result)141   constexpr bool AssignIfValid(Dst* result) const {
142     return IsValid<Dst>() ? ((*result = static_cast<Dst>(state_.value())), true)
143                           : false;
144   }
145 
146   // ValueOrDie() - The primary accessor for the underlying value. If the
147   // current state is not valid it will CHECK and crash.
148   // A range checked destination type can be supplied using the Dst template
149   // parameter, which will trigger a CHECK if the value is not in bounds for
150   // the destination.
151   // The CHECK behavior can be overridden by supplying a handler as a
152   // template parameter, for test code, etc. However, the handler cannot access
153   // the underlying value, and it is not available through other means.
154   template <typename Dst = T, class CheckHandler = CheckOnFailure>
ValueOrDie()155   constexpr StrictNumeric<Dst> ValueOrDie() const {
156     return IsValid<Dst>() ? static_cast<Dst>(state_.value())
157                           : CheckHandler::template HandleFailure<Dst>();
158   }
159 
160   // ValueOrDefault(T default_value) - A convenience method that returns the
161   // current value if the state is valid, and the supplied default_value for
162   // any other state.
163   // A range checked destination type can be supplied using the Dst template
164   // parameter. WARNING: This function may fail to compile or CHECK at runtime
165   // if the supplied default_value is not within range of the destination type.
166   template <typename Dst = T, typename Src>
ValueOrDefault(const Src default_value)167   constexpr StrictNumeric<Dst> ValueOrDefault(const Src default_value) const {
168     return IsValid<Dst>() ? static_cast<Dst>(state_.value())
169                           : checked_cast<Dst>(default_value);
170   }
171 
172   // Returns a checked numeric of the specified type, cast from the current
173   // CheckedNumeric. If the current state is invalid or the destination cannot
174   // represent the result then the returned CheckedNumeric will be invalid.
175   template <typename Dst>
Cast()176   constexpr CheckedNumeric<typename UnderlyingType<Dst>::type> Cast() const {
177     return *this;
178   }
179 
180   // This friend method is available solely for providing more detailed logging
181   // in the the tests. Do not implement it in production code, because the
182   // underlying values may change at any time.
183   template <typename U>
184   friend U GetNumericValueForTest(const CheckedNumeric<U>& src);
185 
186   // Prototypes for the supported arithmetic operator overloads.
187   template <typename Src>
188   CheckedNumeric& operator+=(const Src rhs);
189   template <typename Src>
190   CheckedNumeric& operator-=(const Src rhs);
191   template <typename Src>
192   CheckedNumeric& operator*=(const Src rhs);
193   template <typename Src>
194   CheckedNumeric& operator/=(const Src rhs);
195   template <typename Src>
196   CheckedNumeric& operator%=(const Src rhs);
197   template <typename Src>
198   CheckedNumeric& operator<<=(const Src rhs);
199   template <typename Src>
200   CheckedNumeric& operator>>=(const Src rhs);
201   template <typename Src>
202   CheckedNumeric& operator&=(const Src rhs);
203   template <typename Src>
204   CheckedNumeric& operator|=(const Src rhs);
205   template <typename Src>
206   CheckedNumeric& operator^=(const Src rhs);
207 
208   constexpr CheckedNumeric operator-() const {
209     return CheckedNumeric<T>(
210         NegateWrapper(state_.value()),
211         IsValid() &&
212             (!std::is_signed<T>::value || std::is_floating_point<T>::value ||
213              NegateWrapper(state_.value()) !=
214                  std::numeric_limits<T>::lowest()));
215   }
216 
217   constexpr CheckedNumeric operator~() const {
218     return CheckedNumeric<decltype(InvertWrapper(T()))>(
219         InvertWrapper(state_.value()), IsValid());
220   }
221 
Abs()222   constexpr CheckedNumeric Abs() const {
223     return CheckedNumeric<T>(
224         AbsWrapper(state_.value()),
225         IsValid() &&
226             (!std::is_signed<T>::value || std::is_floating_point<T>::value ||
227              AbsWrapper(state_.value()) != std::numeric_limits<T>::lowest()));
228   }
229 
230   template <typename U>
Max(const U rhs)231   constexpr CheckedNumeric<typename MathWrapper<CheckedMaxOp, T, U>::type> Max(
232       const U rhs) const {
233     using R = typename UnderlyingType<U>::type;
234     using result_type = typename MathWrapper<CheckedMaxOp, T, U>::type;
235     // TODO(jschuh): This can be converted to the MathOp version and remain
236     // constexpr once we have C++14 support.
237     return CheckedNumeric<result_type>(
238         static_cast<result_type>(
239             IsGreater<T, R>::Test(state_.value(), Wrapper<U>::value(rhs))
240                 ? state_.value()
241                 : Wrapper<U>::value(rhs)),
242         state_.is_valid() && Wrapper<U>::is_valid(rhs));
243   }
244 
245   template <typename U>
Min(const U rhs)246   constexpr CheckedNumeric<typename MathWrapper<CheckedMinOp, T, U>::type> Min(
247       const U rhs) const {
248     using R = typename UnderlyingType<U>::type;
249     using result_type = typename MathWrapper<CheckedMinOp, T, U>::type;
250     // TODO(jschuh): This can be converted to the MathOp version and remain
251     // constexpr once we have C++14 support.
252     return CheckedNumeric<result_type>(
253         static_cast<result_type>(
254             IsLess<T, R>::Test(state_.value(), Wrapper<U>::value(rhs))
255                 ? state_.value()
256                 : Wrapper<U>::value(rhs)),
257         state_.is_valid() && Wrapper<U>::is_valid(rhs));
258   }
259 
260   // This function is available only for integral types. It returns an unsigned
261   // integer of the same width as the source type, containing the absolute value
262   // of the source, and properly handling signed min.
263   constexpr CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>
UnsignedAbs()264   UnsignedAbs() const {
265     return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>(
266         SafeUnsignedAbs(state_.value()), state_.is_valid());
267   }
268 
269   CheckedNumeric& operator++() {
270     *this += 1;
271     return *this;
272   }
273 
274   CheckedNumeric operator++(int) {
275     CheckedNumeric value = *this;
276     *this += 1;
277     return value;
278   }
279 
280   CheckedNumeric& operator--() {
281     *this -= 1;
282     return *this;
283   }
284 
285   CheckedNumeric operator--(int) {
286     CheckedNumeric value = *this;
287     *this -= 1;
288     return value;
289   }
290 
291   // These perform the actual math operations on the CheckedNumerics.
292   // Binary arithmetic operations.
293   template <template <typename, typename, typename> class M,
294             typename L,
295             typename R>
MathOp(const L lhs,const R rhs)296   static CheckedNumeric MathOp(const L lhs, const R rhs) {
297     using Math = typename MathWrapper<M, L, R>::math;
298     T result = 0;
299     bool is_valid =
300         Wrapper<L>::is_valid(lhs) && Wrapper<R>::is_valid(rhs) &&
301         Math::Do(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs), &result);
302     return CheckedNumeric<T>(result, is_valid);
303   };
304 
305   // Assignment arithmetic operations.
306   template <template <typename, typename, typename> class M, typename R>
MathOp(const R rhs)307   CheckedNumeric& MathOp(const R rhs) {
308     using Math = typename MathWrapper<M, T, R>::math;
309     T result = 0;  // Using T as the destination saves a range check.
310     bool is_valid = state_.is_valid() && Wrapper<R>::is_valid(rhs) &&
311                     Math::Do(state_.value(), Wrapper<R>::value(rhs), &result);
312     *this = CheckedNumeric<T>(result, is_valid);
313     return *this;
314   };
315 
316  private:
317   CheckedNumericState<T> state_;
318 
319   template <typename Src>
CheckedNumeric(Src value,bool is_valid)320   constexpr CheckedNumeric(Src value, bool is_valid)
321       : state_(value, is_valid) {}
322 
323   // These wrappers allow us to handle state the same way for both
324   // CheckedNumeric and POD arithmetic types.
325   template <typename Src>
326   struct Wrapper {
is_validWrapper327     static constexpr bool is_valid(Src) { return true; }
valueWrapper328     static constexpr Src value(Src value) { return value; }
329   };
330 
331   template <typename Src>
332   struct Wrapper<CheckedNumeric<Src>> {
333     static constexpr bool is_valid(const CheckedNumeric<Src> v) {
334       return v.IsValid();
335     }
336     static constexpr Src value(const CheckedNumeric<Src> v) {
337       return v.state_.value();
338     }
339   };
340 
341   template <typename Src>
342   struct Wrapper<StrictNumeric<Src>> {
343     static constexpr bool is_valid(const StrictNumeric<Src>) { return true; }
344     static constexpr Src value(const StrictNumeric<Src> v) {
345       return static_cast<Src>(v);
346     }
347   };
348 };
349 
350 // Convenience functions to avoid the ugly template disambiguator syntax.
351 template <typename Dst, typename Src>
352 constexpr bool IsValidForType(const CheckedNumeric<Src> value) {
353   return value.template IsValid<Dst>();
354 }
355 
356 template <typename Dst, typename Src>
357 constexpr StrictNumeric<Dst> ValueOrDieForType(
358     const CheckedNumeric<Src> value) {
359   return value.template ValueOrDie<Dst>();
360 }
361 
362 template <typename Dst, typename Src, typename Default>
363 constexpr StrictNumeric<Dst> ValueOrDefaultForType(
364     const CheckedNumeric<Src> value,
365     const Default default_value) {
366   return value.template ValueOrDefault<Dst>(default_value);
367 }
368 
369 // These variadic templates work out the return types.
370 // TODO(jschuh): Rip all this out once we have C++14 non-trailing auto support.
371 template <template <typename, typename, typename> class M,
372           typename L,
373           typename R,
374           typename... Args>
375 struct ResultType;
376 
377 template <template <typename, typename, typename> class M,
378           typename L,
379           typename R>
380 struct ResultType<M, L, R> {
381   using type = typename MathWrapper<M, L, R>::type;
382 };
383 
384 template <template <typename, typename, typename> class M,
385           typename L,
386           typename R,
387           typename... Args>
388 struct ResultType {
389   using type =
390       typename ResultType<M, typename ResultType<M, L, R>::type, Args...>::type;
391 };
392 
393 // Convience wrapper to return a new CheckedNumeric from the provided arithmetic
394 // or CheckedNumericType.
395 template <typename T>
396 constexpr CheckedNumeric<typename UnderlyingType<T>::type> MakeCheckedNum(
397     const T value) {
398   return value;
399 }
400 
401 // These implement the variadic wrapper for the math operations.
402 template <template <typename, typename, typename> class M,
403           typename L,
404           typename R>
405 CheckedNumeric<typename MathWrapper<M, L, R>::type> ChkMathOp(const L lhs,
406                                                               const R rhs) {
407   using Math = typename MathWrapper<M, L, R>::math;
408   return CheckedNumeric<typename Math::result_type>::template MathOp<M>(lhs,
409                                                                         rhs);
410 }
411 
412 // General purpose wrapper template for arithmetic operations.
413 template <template <typename, typename, typename> class M,
414           typename L,
415           typename R,
416           typename... Args>
417 CheckedNumeric<typename ResultType<M, L, R, Args...>::type>
418 ChkMathOp(const L lhs, const R rhs, const Args... args) {
419   auto tmp = ChkMathOp<M>(lhs, rhs);
420   return tmp.IsValid() ? ChkMathOp<M>(tmp, args...)
421                        : decltype(ChkMathOp<M>(tmp, args...))(tmp);
422 }
423 
424 // The following macros are just boilerplate for the standard arithmetic
425 // operator overloads and variadic function templates. A macro isn't the nicest
426 // solution, but it beats rewriting these over and over again.
427 #define BASE_NUMERIC_ARITHMETIC_VARIADIC(NAME)                                \
428   template <typename L, typename R, typename... Args>                         \
429   CheckedNumeric<typename ResultType<Checked##NAME##Op, L, R, Args...>::type> \
430       Check##NAME(const L lhs, const R rhs, const Args... args) {             \
431     return ChkMathOp<Checked##NAME##Op, L, R, Args...>(lhs, rhs, args...);    \
432   }
433 
434 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP)               \
435   /* Binary arithmetic operator for all CheckedNumeric operations. */          \
436   template <typename L, typename R,                                            \
437             typename std::enable_if<IsCheckedOp<L, R>::value>::type* =         \
438                 nullptr>                                                       \
439   CheckedNumeric<typename MathWrapper<Checked##NAME##Op, L, R>::type>          \
440   operator OP(const L lhs, const R rhs) {                                      \
441     return decltype(lhs OP rhs)::template MathOp<Checked##NAME##Op>(lhs, rhs); \
442   }                                                                            \
443   /* Assignment arithmetic operator implementation from CheckedNumeric. */     \
444   template <typename L>                                                        \
445   template <typename R>                                                        \
446   CheckedNumeric<L>& CheckedNumeric<L>::operator COMPOUND_OP(const R rhs) {    \
447     return MathOp<Checked##NAME##Op>(rhs);                                     \
448   }                                                                            \
449   /* Variadic arithmetic functions that return CheckedNumeric. */              \
450   BASE_NUMERIC_ARITHMETIC_VARIADIC(NAME)
451 
452 BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, +=)
453 BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -=)
454 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *=)
455 BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=)
456 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=)
457 BASE_NUMERIC_ARITHMETIC_OPERATORS(Lsh, <<, <<=)
458 BASE_NUMERIC_ARITHMETIC_OPERATORS(Rsh, >>, >>=)
459 BASE_NUMERIC_ARITHMETIC_OPERATORS(And, &, &=)
460 BASE_NUMERIC_ARITHMETIC_OPERATORS(Or, |, |=)
461 BASE_NUMERIC_ARITHMETIC_OPERATORS(Xor, ^, ^=)
462 BASE_NUMERIC_ARITHMETIC_VARIADIC(Max)
463 BASE_NUMERIC_ARITHMETIC_VARIADIC(Min)
464 
465 #undef BASE_NUMERIC_ARITHMETIC_VARIADIC
466 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS
467 
468 // These are some extra StrictNumeric operators to support simple pointer
469 // arithmetic with our result types. Since wrapping on a pointer is always
470 // bad, we trigger the CHECK condition here.
471 template <typename L, typename R>
472 L* operator+(L* lhs, const StrictNumeric<R> rhs) {
473   uintptr_t result = CheckAdd(reinterpret_cast<uintptr_t>(lhs),
474                               CheckMul(sizeof(L), static_cast<R>(rhs)))
475                          .template ValueOrDie<uintptr_t>();
476   return reinterpret_cast<L*>(result);
477 }
478 
479 template <typename L, typename R>
480 L* operator-(L* lhs, const StrictNumeric<R> rhs) {
481   uintptr_t result = CheckSub(reinterpret_cast<uintptr_t>(lhs),
482                               CheckMul(sizeof(L), static_cast<R>(rhs)))
483                          .template ValueOrDie<uintptr_t>();
484   return reinterpret_cast<L*>(result);
485 }
486 
487 }  // namespace internal
488 
489 using internal::CheckedNumeric;
490 using internal::IsValidForType;
491 using internal::ValueOrDieForType;
492 using internal::ValueOrDefaultForType;
493 using internal::MakeCheckedNum;
494 using internal::CheckMax;
495 using internal::CheckMin;
496 using internal::CheckAdd;
497 using internal::CheckSub;
498 using internal::CheckMul;
499 using internal::CheckDiv;
500 using internal::CheckMod;
501 using internal::CheckLsh;
502 using internal::CheckRsh;
503 using internal::CheckAnd;
504 using internal::CheckOr;
505 using internal::CheckXor;
506 
507 }  // namespace base
508 }  // namespace pdfium
509 
510 #endif  // PDFIUM_THIRD_PARTY_BASE_NUMERICS_SAFE_MATH_H_
511