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