[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.0' - external/pdfium

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Thu Dec 17 12:57:40 UTC 2020


 external/pdfium/UnpackedTarball_pdfium.mk   |    3 
 external/pdfium/msvc2015.patch.1            |  202 +
 external/pdfium/pdfium4137-numerics.patch.3 | 3364 ++++++++++++++++++++++++++++
 3 files changed, 3569 insertions(+)

New commits:
commit b0558aee1b69217f06ff7205f2b09cfb54f2a428
Author:     Michael Stahl <MichaelSt at cib.de>
AuthorDate: Thu Dec 3 17:42:18 2020 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Dec 17 13:56:58 2020 +0100

    pdfium: MSVC 2015 build
    
    (cherry picked from commit 7ac3af8c89af7d481c027df75026f390258e6e5a)
    
    Change-Id: I5ea89841fafe3ea96fa256e91151eceb8235731e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107871
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>

diff --git a/external/pdfium/UnpackedTarball_pdfium.mk b/external/pdfium/UnpackedTarball_pdfium.mk
index f4643376cee0..8b12e494f94b 100644
--- a/external/pdfium/UnpackedTarball_pdfium.mk
+++ b/external/pdfium/UnpackedTarball_pdfium.mk
@@ -14,6 +14,9 @@ pdfium_patches += build.patch.1
 # Avoids Windows 8 build dependency.
 pdfium_patches += windows7.patch.1
 pdfium_patches += c++20-comparison.patch
+ifeq (MSC,$(COM))
+pdfium_patches += pdfium4137-numerics.patch.3 msvc2015.patch.1
+endif
 
 $(eval $(call gb_UnpackedTarball_UnpackedTarball,pdfium))
 
diff --git a/external/pdfium/msvc2015.patch.1 b/external/pdfium/msvc2015.patch.1
new file mode 100644
index 000000000000..36cb5332c7b0
--- /dev/null
+++ b/external/pdfium/msvc2015.patch.1
@@ -0,0 +1,202 @@
+Fix MSVC 2015 build
+
+--- pdfium/third_party/base/optional.h.orig	2020-10-26 19:26:04.000000000 +0100
++++ pdfium/third_party/base/optional.h	2020-12-03 16:00:54.879883100 +0100
+@@ -36,7 +36,7 @@
+ struct OptionalStorageBase {
+   // Provide non-defaulted default ctor to make sure it's not deleted by
+   // non-trivial T::T() in the union.
+-  constexpr OptionalStorageBase() : dummy_() {}
++  OptionalStorageBase() : dummy_() {}
+ 
+   template <class... Args>
+   constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
+@@ -88,7 +88,7 @@
+ struct OptionalStorageBase<T, true /* trivially destructible */> {
+   // Provide non-defaulted default ctor to make sure it's not deleted by
+   // non-trivial T::T() in the union.
+-  constexpr OptionalStorageBase() : dummy_() {}
++  OptionalStorageBase() : dummy_() {}
+ 
+   template <class... Args>
+   constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
+@@ -607,32 +607,32 @@
+     return *this;
+   }
+ 
+-  constexpr const T* operator->() const {
++  const T* operator->() const {
+     CHECK(storage_.is_populated_);
+     return &storage_.value_;
+   }
+ 
+-  constexpr T* operator->() {
++  T* operator->() {
+     CHECK(storage_.is_populated_);
+     return &storage_.value_;
+   }
+ 
+-  constexpr const T& operator*() const & {
++  const T& operator*() const & {
+     CHECK(storage_.is_populated_);
+     return storage_.value_;
+   }
+ 
+-  constexpr T& operator*() & {
++  T& operator*() & {
+     CHECK(storage_.is_populated_);
+     return storage_.value_;
+   }
+ 
+-  constexpr const T&& operator*() const && {
++  const T&& operator*() const && {
+     CHECK(storage_.is_populated_);
+     return std::move(storage_.value_);
+   }
+ 
+-  constexpr T&& operator*() && {
++  T&& operator*() && {
+     CHECK(storage_.is_populated_);
+     return std::move(storage_.value_);
+   }
+@@ -641,22 +641,22 @@
+ 
+   constexpr bool has_value() const { return storage_.is_populated_; }
+ 
+-  constexpr T& value() & {
++  T& value() & {
+     CHECK(storage_.is_populated_);
+     return storage_.value_;
+   }
+ 
+-  constexpr const T& value() const & {
++  const T& value() const & {
+     CHECK(storage_.is_populated_);
+     return storage_.value_;
+   }
+ 
+-  constexpr T&& value() && {
++  T&& value() && {
+     CHECK(storage_.is_populated_);
+     return std::move(storage_.value_);
+   }
+ 
+-  constexpr const T&& value() const && {
++  const T&& value() const && {
+     CHECK(storage_.is_populated_);
+     return std::move(storage_.value_);
+   }
+--- pdfium/third_party/base/span.h.orig	2020-10-26 19:26:04.000000000 +0100
++++ pdfium/third_party/base/span.h	2020-12-03 16:28:15.642138100 +0100
+@@ -193,7 +193,7 @@
+ 
+   // TODO(dcheng): Implement construction from a |begin| and |end| pointer.
+   template <size_t N>
+-  constexpr span(T (&array)[N]) noexcept : span(array, N) {}
++  span(T (&array)[N]) noexcept : span(array, N) {}
+   // TODO(dcheng): Implement construction from std::array.
+   // Conversion from a container that provides |T* data()| and |integral_type
+   // size()|.
+--- pdfium/core/fpdfapi/page/cpdf_colorspace.cpp.orig	2020-12-03 16:54:15.514659400 +0100
++++ pdfium/core/fpdfapi/page/cpdf_colorspace.cpp	2020-12-03 16:38:52.167650200 +0100
+@@ -905,7 +905,7 @@
+     float R;
+     float G;
+     float B;
+-    GetRGB(lab, &R, &G, &B);
++    GetRGB(pdfium::span<float>(lab), &R, &G, &B);
+     pDestBuf[0] = static_cast<int32_t>(B * 255);
+     pDestBuf[1] = static_cast<int32_t>(G * 255);
+     pDestBuf[2] = static_cast<int32_t>(R * 255);
+--- pdfium/core/fpdfapi/page/cpdf_meshstream.cpp.orig	2020-12-03 16:54:09.233498800 +0100
++++ pdfium/core/fpdfapi/page/cpdf_meshstream.cpp	2020-12-03 16:41:29.173766500 +0100
+@@ -209,7 +209,7 @@
+       func->Call(color_value, 1, result, &nResults);
+   }
+ 
+-  m_pCS->GetRGB(result, &r, &g, &b);
++  m_pCS->GetRGB(pdfium::span<float>(result), &r, &g, &b);
+   return std::tuple<float, float, float>(r, g, b);
+ }
+ 
+--- pdfium/core/fpdfapi/parser/cpdf_security_handler.cpp.orig	2020-12-03 16:53:56.077095400 +0100
++++ pdfium/core/fpdfapi/parser/cpdf_security_handler.cpp	2020-12-03 16:44:23.951334200 +0100
+@@ -481,7 +481,7 @@
+   uint8_t passcode[32];
+   GetPassCode(owner_password, passcode);
+   uint8_t digest[16];
+-  CRYPT_MD5Generate(passcode, digest);
++  CRYPT_MD5Generate(pdfium::span<uint8_t>(passcode), digest);
+   if (m_Revision >= 3) {
+     for (uint32_t i = 0; i < 50; i++)
+       CRYPT_MD5Generate(digest, digest);
+@@ -570,10 +570,10 @@
+     uint8_t passcode[32];
+     GetPassCode(owner_password_copy, passcode);
+     uint8_t digest[16];
+-    CRYPT_MD5Generate(passcode, digest);
++    CRYPT_MD5Generate(pdfium::span<uint8_t>(passcode), digest);
+     if (m_Revision >= 3) {
+       for (uint32_t i = 0; i < 50; i++)
+-        CRYPT_MD5Generate(digest, digest);
++        CRYPT_MD5Generate(pdfium::span<uint8_t>(digest), digest);
+     }
+     uint8_t enckey[32];
+     memcpy(enckey, digest, key_len);
+--- pdfium/core/fpdfapi/page/cpdf_dib.cpp.orig	2020-12-03 16:53:44.548444600 +0100
++++ pdfium/core/fpdfapi/page/cpdf_dib.cpp	2020-12-03 16:49:11.937584700 +0100
+@@ -874,7 +874,7 @@
+     color_values[0] += m_CompData[0].m_DecodeStep;
+     color_values[1] += m_CompData[0].m_DecodeStep;
+     color_values[2] += m_CompData[0].m_DecodeStep;
+-    m_pColorSpace->GetRGB(color_values, &R, &G, &B);
++    m_pColorSpace->GetRGB(pdfium::span<float>(color_values), &R, &G, &B);
+     FX_ARGB argb1 = ArgbEncode(255, FXSYS_roundf(R * 255),
+                                FXSYS_roundf(G * 255), FXSYS_roundf(B * 255));
+     if (argb0 != 0xFF000000 || argb1 != 0xFFFFFFFF) {
+--- pdfium/third_party/base/allocator/partition_allocator/partition_alloc.cc.orig	2020-12-03 17:09:02.887283800 +0100
++++ pdfium/third_party/base/allocator/partition_allocator/partition_alloc.cc	2020-12-03 17:07:22.198993800 +0100
+@@ -67,12 +67,12 @@
+   // Chained hooks are not supported. Registering a non-null hook when a
+   // non-null hook is already registered indicates somebody is trying to
+   // overwrite a hook.
+-  CHECK((!allocation_observer_hook_ && !free_observer_hook_) ||
++  CHECK((!allocation_observer_hook_.load() && !free_observer_hook_.load()) ||
+         (!alloc_hook && !free_hook));
+   allocation_observer_hook_ = alloc_hook;
+   free_observer_hook_ = free_hook;
+ 
+-  hooks_enabled_ = allocation_observer_hook_ || allocation_override_hook_;
++  hooks_enabled_ = allocation_observer_hook_.load() || allocation_override_hook_.load();
+ }
+ 
+ void PartitionAllocHooks::SetOverrideHooks(AllocationOverrideHook* alloc_hook,
+@@ -80,14 +80,14 @@
+                                            ReallocOverrideHook realloc_hook) {
+   subtle::SpinLock::Guard guard(set_hooks_lock_);
+ 
+-  CHECK((!allocation_override_hook_ && !free_override_hook_ &&
+-         !realloc_override_hook_) ||
++  CHECK((!allocation_override_hook_.load() && !free_override_hook_.load() &&
++         !realloc_override_hook_.load()) ||
+         (!alloc_hook && !free_hook && !realloc_hook));
+   allocation_override_hook_ = alloc_hook;
+   free_override_hook_ = free_hook;
+   realloc_override_hook_ = realloc_hook;
+ 
+-  hooks_enabled_ = allocation_observer_hook_ || allocation_override_hook_;
++  hooks_enabled_ = allocation_observer_hook_.load() || allocation_override_hook_.load();
+ }
+ 
+ void PartitionAllocHooks::AllocationObserverHookIfEnabled(
+--- pdfium/third_party/base/allocator/partition_allocator/partition_page.h.orig	2020-12-03 17:13:56.944624000 +0100
++++ pdfium/third_party/base/allocator/partition_allocator/partition_page.h	2020-12-03 17:13:34.385932300 +0100
+@@ -25,6 +25,8 @@
+ struct DeferredUnmap {
+   void* ptr = nullptr;
+   size_t size = 0;
++  DeferredUnmap(void* const p, size_t const s) : ptr(p), size(s) {}
++  DeferredUnmap() = default;
+   // In most cases there is no page to unmap and ptr == nullptr. This function
+   // is inlined to avoid the overhead of a function call in the common case.
+   ALWAYS_INLINE void Run();
diff --git a/external/pdfium/pdfium4137-numerics.patch.3 b/external/pdfium/pdfium4137-numerics.patch.3
new file mode 100644
index 000000000000..7d27ccd7f3cb
--- /dev/null
+++ b/external/pdfium/pdfium4137-numerics.patch.3
@@ -0,0 +1,3364 @@
+Restore numerics headers from release 4137
+
+diff -Naur workdir/UnpackedTarball/pdfium/third_party/base/numerics/checked_math.h workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/checked_math.h
+--- workdir/UnpackedTarball/pdfium/third_party/base/numerics/checked_math.h	2020-10-26 19:26:04.000000000 +0100
++++ workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/checked_math.h	1970-01-01 01:00:00.000000000 +0100
+@@ -1,395 +0,0 @@
+-// Copyright 2017 The Chromium Authors. All rights reserved.
+-// Use of this source code is governed by a BSD-style license that can be
+-// found in the LICENSE file.
+-
+-#ifndef THIRD_PARTY_BASE_NUMERICS_CHECKED_MATH_H_
+-#define THIRD_PARTY_BASE_NUMERICS_CHECKED_MATH_H_
+-
+-#include <stddef.h>
+-
+-#include <limits>
+-#include <type_traits>
+-
+-#include "third_party/base/numerics/checked_math_impl.h"
+-
+-namespace pdfium {
+-namespace base {
+-namespace internal {
+-
+-template <typename T>
+-class CheckedNumeric {
+-  static_assert(std::is_arithmetic<T>::value,
+-                "CheckedNumeric<T>: T must be a numeric type.");
+-
+- public:
+-  using type = T;
+-
+-  constexpr CheckedNumeric() = default;
+-
+-  // Copy constructor.
+-  template <typename Src>
+-  constexpr CheckedNumeric(const CheckedNumeric<Src>& rhs)
+-      : state_(rhs.state_.value(), rhs.IsValid()) {}
+-
+-  template <typename Src>
+-  friend class CheckedNumeric;
+-
+-  // This is not an explicit constructor because we implicitly upgrade regular
+-  // numerics to CheckedNumerics to make them easier to use.
+-  template <typename Src>
+-  constexpr CheckedNumeric(Src value)  // NOLINT(runtime/explicit)
+-      : state_(value) {
+-    static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric.");
+-  }
+-
+-  // This is not an explicit constructor because we want a seamless conversion
+-  // from StrictNumeric types.
+-  template <typename Src>
+-  constexpr CheckedNumeric(
+-      StrictNumeric<Src> value)  // NOLINT(runtime/explicit)
+-      : state_(static_cast<Src>(value)) {}
+-
+-  // IsValid() - The public API to test if a CheckedNumeric is currently valid.
+-  // A range checked destination type can be supplied using the Dst template
+-  // parameter.
+-  template <typename Dst = T>
+-  constexpr bool IsValid() const {
+-    return state_.is_valid() &&
+-           IsValueInRangeForNumericType<Dst>(state_.value());
+-  }
+-
+-  // AssignIfValid(Dst) - Assigns the underlying value if it is currently valid
+-  // and is within the range supported by the destination type. Returns true if
+-  // successful and false otherwise.
+-  template <typename Dst>
+-#if defined(__clang__) || defined(__GNUC__)
+-  __attribute__((warn_unused_result))
+-#elif defined(_MSC_VER)
+-  _Check_return_
+-#endif
+-  constexpr bool
+-  AssignIfValid(Dst* result) const {
+-    return BASE_NUMERICS_LIKELY(IsValid<Dst>())
+-               ? ((*result = static_cast<Dst>(state_.value())), true)
+-               : false;
+-  }
+-
+-  // ValueOrDie() - The primary accessor for the underlying value. If the
+-  // current state is not valid it will CHECK and crash.
+-  // A range checked destination type can be supplied using the Dst template
+-  // parameter, which will trigger a CHECK if the value is not in bounds for
+-  // the destination.
+-  // The CHECK behavior can be overridden by supplying a handler as a
+-  // template parameter, for test code, etc. However, the handler cannot access
+-  // the underlying value, and it is not available through other means.
+-  template <typename Dst = T, class CheckHandler = CheckOnFailure>
+-  constexpr StrictNumeric<Dst> ValueOrDie() const {
+-    return BASE_NUMERICS_LIKELY(IsValid<Dst>())
+-               ? static_cast<Dst>(state_.value())
+-               : CheckHandler::template HandleFailure<Dst>();
+-  }
+-
+-  // ValueOrDefault(T default_value) - A convenience method that returns the
+-  // current value if the state is valid, and the supplied default_value for
+-  // any other state.
+-  // A range checked destination type can be supplied using the Dst template
+-  // parameter. WARNING: This function may fail to compile or CHECK at runtime
+-  // if the supplied default_value is not within range of the destination type.
+-  template <typename Dst = T, typename Src>
+-  constexpr StrictNumeric<Dst> ValueOrDefault(const Src default_value) const {
+-    return BASE_NUMERICS_LIKELY(IsValid<Dst>())
+-               ? static_cast<Dst>(state_.value())
+-               : checked_cast<Dst>(default_value);
+-  }
+-
+-  // Returns a checked numeric of the specified type, cast from the current
+-  // CheckedNumeric. If the current state is invalid or the destination cannot
+-  // represent the result then the returned CheckedNumeric will be invalid.
+-  template <typename Dst>
+-  constexpr CheckedNumeric<typename UnderlyingType<Dst>::type> Cast() const {
+-    return *this;
+-  }
+-
+-  // This friend method is available solely for providing more detailed logging
+-  // in the the tests. Do not implement it in production code, because the
+-  // underlying values may change at any time.
+-  template <typename U>
+-  friend U GetNumericValueForTest(const CheckedNumeric<U>& src);
+-
+-  // Prototypes for the supported arithmetic operator overloads.
+-  template <typename Src>
+-  constexpr CheckedNumeric& operator+=(const Src rhs);
+-  template <typename Src>
+-  constexpr CheckedNumeric& operator-=(const Src rhs);
+-  template <typename Src>
+-  constexpr CheckedNumeric& operator*=(const Src rhs);
+-  template <typename Src>
+-  constexpr CheckedNumeric& operator/=(const Src rhs);
+-  template <typename Src>
+-  constexpr CheckedNumeric& operator%=(const Src rhs);
+-  template <typename Src>
+-  constexpr CheckedNumeric& operator<<=(const Src rhs);
+-  template <typename Src>
+-  constexpr CheckedNumeric& operator>>=(const Src rhs);
+-  template <typename Src>
+-  constexpr CheckedNumeric& operator&=(const Src rhs);
+-  template <typename Src>
+-  constexpr CheckedNumeric& operator|=(const Src rhs);
+-  template <typename Src>
+-  constexpr CheckedNumeric& operator^=(const Src rhs);
+-
+-  constexpr CheckedNumeric operator-() const {
+-    // The negation of two's complement int min is int min, so we simply
+-    // check for that in the constexpr case.
+-    // We use an optimized code path for a known run-time variable.
+-    return MustTreatAsConstexpr(state_.value()) || !std::is_signed<T>::value ||
+-                   std::is_floating_point<T>::value
+-               ? CheckedNumeric<T>(
+-                     NegateWrapper(state_.value()),
+-                     IsValid() && (!std::is_signed<T>::value ||
+-                                   std::is_floating_point<T>::value ||
+-                                   NegateWrapper(state_.value()) !=
+-                                       std::numeric_limits<T>::lowest()))
+-               : FastRuntimeNegate();
+-  }
+-
+-  constexpr CheckedNumeric operator~() const {
+-    return CheckedNumeric<decltype(InvertWrapper(T()))>(
+-        InvertWrapper(state_.value()), IsValid());
+-  }
+-
+-  constexpr CheckedNumeric Abs() const {
+-    return !IsValueNegative(state_.value()) ? *this : -*this;
+-  }
+-
+-  template <typename U>
+-  constexpr CheckedNumeric<typename MathWrapper<CheckedMaxOp, T, U>::type> Max(
+-      const U rhs) const {
+-    using R = typename UnderlyingType<U>::type;
+-    using result_type = typename MathWrapper<CheckedMaxOp, T, U>::type;
+-    // TODO(jschuh): This can be converted to the MathOp version and remain
+-    // constexpr once we have C++14 support.
+-    return CheckedNumeric<result_type>(
+-        static_cast<result_type>(
+-            IsGreater<T, R>::Test(state_.value(), Wrapper<U>::value(rhs))
+-                ? state_.value()
+-                : Wrapper<U>::value(rhs)),
+-        state_.is_valid() && Wrapper<U>::is_valid(rhs));
+-  }
+-
+-  template <typename U>
+-  constexpr CheckedNumeric<typename MathWrapper<CheckedMinOp, T, U>::type> Min(
+-      const U rhs) const {
+-    using R = typename UnderlyingType<U>::type;
+-    using result_type = typename MathWrapper<CheckedMinOp, T, U>::type;
+-    // TODO(jschuh): This can be converted to the MathOp version and remain
+-    // constexpr once we have C++14 support.
+-    return CheckedNumeric<result_type>(
+-        static_cast<result_type>(
+-            IsLess<T, R>::Test(state_.value(), Wrapper<U>::value(rhs))
+-                ? state_.value()
+-                : Wrapper<U>::value(rhs)),
+-        state_.is_valid() && Wrapper<U>::is_valid(rhs));
+-  }
+-
+-  // This function is available only for integral types. It returns an unsigned
+-  // integer of the same width as the source type, containing the absolute value
+-  // of the source, and properly handling signed min.
+-  constexpr CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>
+-  UnsignedAbs() const {
+-    return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>(
+-        SafeUnsignedAbs(state_.value()), state_.is_valid());
+-  }
+-
+-  constexpr CheckedNumeric& operator++() {
+-    *this += 1;
+-    return *this;
+-  }
+-
+-  constexpr CheckedNumeric operator++(int) {
+-    CheckedNumeric value = *this;
+-    *this += 1;
+-    return value;
+-  }
+-
+-  constexpr CheckedNumeric& operator--() {
+-    *this -= 1;
+-    return *this;
+-  }
+-
+-  constexpr CheckedNumeric operator--(int) {
+-    CheckedNumeric value = *this;
+-    *this -= 1;
+-    return value;
+-  }
+-
+-  // These perform the actual math operations on the CheckedNumerics.
+-  // Binary arithmetic operations.
+-  template <template <typename, typename, typename> class M,
+-            typename L,
+-            typename R>
+-  static constexpr CheckedNumeric MathOp(const L lhs, const R rhs) {
+-    using Math = typename MathWrapper<M, L, R>::math;
+-    T result = 0;
+-    bool is_valid =
+-        Wrapper<L>::is_valid(lhs) && Wrapper<R>::is_valid(rhs) &&
+-        Math::Do(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs), &result);
+-    return CheckedNumeric<T>(result, is_valid);
+-  }
+-
+-  // Assignment arithmetic operations.
+-  template <template <typename, typename, typename> class M, typename R>
+-  constexpr CheckedNumeric& MathOp(const R rhs) {
+-    using Math = typename MathWrapper<M, T, R>::math;
+-    T result = 0;  // Using T as the destination saves a range check.
+-    bool is_valid = state_.is_valid() && Wrapper<R>::is_valid(rhs) &&
+-                    Math::Do(state_.value(), Wrapper<R>::value(rhs), &result);
+-    *this = CheckedNumeric<T>(result, is_valid);
+-    return *this;
+-  }
+-
+- private:
+-  CheckedNumericState<T> state_;
+-
+-  CheckedNumeric FastRuntimeNegate() const {
+-    T result;
+-    bool success = CheckedSubOp<T, T>::Do(T(0), state_.value(), &result);
+-    return CheckedNumeric<T>(result, IsValid() && success);
+-  }
+-
+-  template <typename Src>
+-  constexpr CheckedNumeric(Src value, bool is_valid)
+-      : state_(value, is_valid) {}
+-
+-  // These wrappers allow us to handle state the same way for both
+-  // CheckedNumeric and POD arithmetic types.
+-  template <typename Src>
+-  struct Wrapper {
+-    static constexpr bool is_valid(Src) { return true; }
+-    static constexpr Src value(Src value) { return value; }
+-  };
+-
+-  template <typename Src>
+-  struct Wrapper<CheckedNumeric<Src>> {
+-    static constexpr bool is_valid(const CheckedNumeric<Src> v) {
+-      return v.IsValid();
+-    }
+-    static constexpr Src value(const CheckedNumeric<Src> v) {
+-      return v.state_.value();
+-    }
+-  };
+-
+-  template <typename Src>
+-  struct Wrapper<StrictNumeric<Src>> {
+-    static constexpr bool is_valid(const StrictNumeric<Src>) { return true; }
+-    static constexpr Src value(const StrictNumeric<Src> v) {
+-      return static_cast<Src>(v);
+-    }
+-  };
+-};
+-
+-// Convenience functions to avoid the ugly template disambiguator syntax.
+-template <typename Dst, typename Src>
+-constexpr bool IsValidForType(const CheckedNumeric<Src> value) {
+-  return value.template IsValid<Dst>();
+-}
+-
+-template <typename Dst, typename Src>
+-constexpr StrictNumeric<Dst> ValueOrDieForType(
+-    const CheckedNumeric<Src> value) {
+-  return value.template ValueOrDie<Dst>();
+-}
+-
+-template <typename Dst, typename Src, typename Default>
+-constexpr StrictNumeric<Dst> ValueOrDefaultForType(
+-    const CheckedNumeric<Src> value,
+-    const Default default_value) {
+-  return value.template ValueOrDefault<Dst>(default_value);
+-}
+-
+-// Convience wrapper to return a new CheckedNumeric from the provided arithmetic
+-// or CheckedNumericType.
+-template <typename T>
+-constexpr CheckedNumeric<typename UnderlyingType<T>::type> MakeCheckedNum(
+-    const T value) {
+-  return value;
+-}
+-
+-// These implement the variadic wrapper for the math operations.
+-template <template <typename, typename, typename> class M,
+-          typename L,
+-          typename R>
+-constexpr CheckedNumeric<typename MathWrapper<M, L, R>::type> CheckMathOp(
+-    const L lhs,
+-    const R rhs) {
+-  using Math = typename MathWrapper<M, L, R>::math;
+-  return CheckedNumeric<typename Math::result_type>::template MathOp<M>(lhs,
+-                                                                        rhs);
+-}
+-
+-// General purpose wrapper template for arithmetic operations.
+-template <template <typename, typename, typename> class M,
+-          typename L,
+-          typename R,
+-          typename... Args>
+-constexpr CheckedNumeric<typename ResultType<M, L, R, Args...>::type>
+-CheckMathOp(const L lhs, const R rhs, const Args... args) {
+-  return CheckMathOp<M>(CheckMathOp<M>(lhs, rhs), args...);
+-}
+-
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Add, +, +=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Sub, -, -=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mul, *, *=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Div, /, /=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mod, %, %=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Lsh, <<, <<=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Rsh, >>, >>=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, And, &, &=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Or, |, |=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Xor, ^, ^=)
+-BASE_NUMERIC_ARITHMETIC_VARIADIC(Checked, Check, Max)
+-BASE_NUMERIC_ARITHMETIC_VARIADIC(Checked, Check, Min)
+-
+-// These are some extra StrictNumeric operators to support simple pointer
+-// arithmetic with our result types. Since wrapping on a pointer is always
+-// bad, we trigger the CHECK condition here.
+-template <typename L, typename R>
+-L* operator+(L* lhs, const StrictNumeric<R> rhs) {
+-  uintptr_t result = CheckAdd(reinterpret_cast<uintptr_t>(lhs),
+-                              CheckMul(sizeof(L), static_cast<R>(rhs)))
+-                         .template ValueOrDie<uintptr_t>();
+-  return reinterpret_cast<L*>(result);
+-}
+-
+-template <typename L, typename R>
+-L* operator-(L* lhs, const StrictNumeric<R> rhs) {
+-  uintptr_t result = CheckSub(reinterpret_cast<uintptr_t>(lhs),
+-                              CheckMul(sizeof(L), static_cast<R>(rhs)))
+-                         .template ValueOrDie<uintptr_t>();
+-  return reinterpret_cast<L*>(result);
+-}
+-
+-}  // namespace internal
+-
+-using internal::CheckedNumeric;
+-using internal::IsValidForType;
+-using internal::ValueOrDieForType;
+-using internal::ValueOrDefaultForType;
+-using internal::MakeCheckedNum;
+-using internal::CheckMax;
+-using internal::CheckMin;
+-using internal::CheckAdd;
+-using internal::CheckSub;
+-using internal::CheckMul;
+-using internal::CheckDiv;
+-using internal::CheckMod;
+-using internal::CheckLsh;
+-using internal::CheckRsh;
+-using internal::CheckAnd;
+-using internal::CheckOr;
+-using internal::CheckXor;
+-
+-}  // namespace base
+-}  // namespace pdfium
+-
+-#endif  // THIRD_PARTY_BASE_NUMERICS_CHECKED_MATH_H_
+diff -Naur workdir/UnpackedTarball/pdfium/third_party/base/numerics/checked_math_impl.h workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/checked_math_impl.h
+--- workdir/UnpackedTarball/pdfium/third_party/base/numerics/checked_math_impl.h	2020-10-26 19:26:04.000000000 +0100
++++ workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/checked_math_impl.h	1970-01-01 01:00:00.000000000 +0100
+@@ -1,579 +0,0 @@
+-// Copyright 2017 The Chromium Authors. All rights reserved.
+-// Use of this source code is governed by a BSD-style license that can be
+-// found in the LICENSE file.
+-
+-#ifndef THIRD_PARTY_BASE_NUMERICS_CHECKED_MATH_IMPL_H_
+-#define THIRD_PARTY_BASE_NUMERICS_CHECKED_MATH_IMPL_H_
+-
+-#include <stddef.h>
+-#include <stdint.h>
+-
+-#include <climits>
+-#include <cmath>
+-#include <cstdlib>
+-#include <limits>
+-#include <type_traits>
+-
+-#include "third_party/base/numerics/safe_conversions.h"
+-#include "third_party/base/numerics/safe_math_shared_impl.h"
+-
+-namespace pdfium {
+-namespace base {
+-namespace internal {
+-
+-template <typename T>
+-constexpr bool CheckedAddImpl(T x, T y, T* result) {
+-  static_assert(std::is_integral<T>::value, "Type must be integral");
+-  // Since the value of x+y is undefined if we have a signed type, we compute
+-  // it using the unsigned type of the same size.
+-  using UnsignedDst = typename std::make_unsigned<T>::type;
+-  using SignedDst = typename std::make_signed<T>::type;
+-  UnsignedDst ux = static_cast<UnsignedDst>(x);
+-  UnsignedDst uy = static_cast<UnsignedDst>(y);
+-  UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy);
+-  *result = static_cast<T>(uresult);
+-  // Addition is valid if the sign of (x + y) is equal to either that of x or
+-  // that of y.
+-  return (std::is_signed<T>::value)
+-             ? static_cast<SignedDst>((uresult ^ ux) & (uresult ^ uy)) >= 0
+-             : uresult >= uy;  // Unsigned is either valid or underflow.
+-}
+-
+-template <typename T, typename U, class Enable = void>
+-struct CheckedAddOp {};
+-
+-template <typename T, typename U>
+-struct CheckedAddOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename MaxExponentPromotion<T, U>::type;
+-  template <typename V>
+-  static constexpr bool Do(T x, U y, V* result) {
+-    // TODO(jschuh) Make this "constexpr if" once we're C++17.
+-    if (CheckedAddFastOp<T, U>::is_supported)
+-      return CheckedAddFastOp<T, U>::Do(x, y, result);
+-
+-    // Double the underlying type up to a full machine word.
+-    using FastPromotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+-    using Promotion =
+-        typename std::conditional<(IntegerBitsPlusSign<FastPromotion>::value >
+-                                   IntegerBitsPlusSign<intptr_t>::value),
+-                                  typename BigEnoughPromotion<T, U>::type,
+-                                  FastPromotion>::type;
+-    // Fail if either operand is out of range for the promoted type.
+-    // TODO(jschuh): This could be made to work for a broader range of values.
+-    if (BASE_NUMERICS_UNLIKELY(!IsValueInRangeForNumericType<Promotion>(x) ||
+-                               !IsValueInRangeForNumericType<Promotion>(y))) {
+-      return false;
+-    }
+-
+-    Promotion presult = {};
+-    bool is_valid = true;
+-    if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
+-      presult = static_cast<Promotion>(x) + static_cast<Promotion>(y);
+-    } else {
+-      is_valid = CheckedAddImpl(static_cast<Promotion>(x),
+-                                static_cast<Promotion>(y), &presult);
+-    }
+-    *result = static_cast<V>(presult);
+-    return is_valid && IsValueInRangeForNumericType<V>(presult);
+-  }
+-};
+-
+-template <typename T>
+-constexpr bool CheckedSubImpl(T x, T y, T* result) {
+-  static_assert(std::is_integral<T>::value, "Type must be integral");
+-  // Since the value of x+y is undefined if we have a signed type, we compute
+-  // it using the unsigned type of the same size.
+-  using UnsignedDst = typename std::make_unsigned<T>::type;
+-  using SignedDst = typename std::make_signed<T>::type;
+-  UnsignedDst ux = static_cast<UnsignedDst>(x);
+-  UnsignedDst uy = static_cast<UnsignedDst>(y);
+-  UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy);
+-  *result = static_cast<T>(uresult);
+-  // Subtraction is valid if either x and y have same sign, or (x-y) and x have
+-  // the same sign.
+-  return (std::is_signed<T>::value)
+-             ? static_cast<SignedDst>((uresult ^ ux) & (ux ^ uy)) >= 0
+-             : x >= y;
+-}
+-
+-template <typename T, typename U, class Enable = void>
+-struct CheckedSubOp {};
+-
+-template <typename T, typename U>
+-struct CheckedSubOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename MaxExponentPromotion<T, U>::type;
+-  template <typename V>
+-  static constexpr bool Do(T x, U y, V* result) {
+-    // TODO(jschuh) Make this "constexpr if" once we're C++17.
+-    if (CheckedSubFastOp<T, U>::is_supported)
+-      return CheckedSubFastOp<T, U>::Do(x, y, result);
+-
+-    // Double the underlying type up to a full machine word.
+-    using FastPromotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+-    using Promotion =
+-        typename std::conditional<(IntegerBitsPlusSign<FastPromotion>::value >
+-                                   IntegerBitsPlusSign<intptr_t>::value),
+-                                  typename BigEnoughPromotion<T, U>::type,
+-                                  FastPromotion>::type;
+-    // Fail if either operand is out of range for the promoted type.
+-    // TODO(jschuh): This could be made to work for a broader range of values.
+-    if (BASE_NUMERICS_UNLIKELY(!IsValueInRangeForNumericType<Promotion>(x) ||
+-                               !IsValueInRangeForNumericType<Promotion>(y))) {
+-      return false;
+-    }
+-
+-    Promotion presult = {};
+-    bool is_valid = true;
+-    if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
+-      presult = static_cast<Promotion>(x) - static_cast<Promotion>(y);
+-    } else {
+-      is_valid = CheckedSubImpl(static_cast<Promotion>(x),
+-                                static_cast<Promotion>(y), &presult);
+-    }
+-    *result = static_cast<V>(presult);
+-    return is_valid && IsValueInRangeForNumericType<V>(presult);
+-  }
+-};
+-
+-template <typename T>
+-constexpr bool CheckedMulImpl(T x, T y, T* result) {
+-  static_assert(std::is_integral<T>::value, "Type must be integral");
+-  // Since the value of x*y is potentially undefined if we have a signed type,
+-  // we compute it using the unsigned type of the same size.
+-  using UnsignedDst = typename std::make_unsigned<T>::type;
+-  using SignedDst = typename std::make_signed<T>::type;
+-  const UnsignedDst ux = SafeUnsignedAbs(x);
+-  const UnsignedDst uy = SafeUnsignedAbs(y);
+-  UnsignedDst uresult = static_cast<UnsignedDst>(ux * uy);
+-  const bool is_negative =
+-      std::is_signed<T>::value && static_cast<SignedDst>(x ^ y) < 0;
+-  *result = is_negative ? 0 - uresult : uresult;
+-  // We have a fast out for unsigned identity or zero on the second operand.
+-  // After that it's an unsigned overflow check on the absolute value, with
+-  // a +1 bound for a negative result.
+-  return uy <= UnsignedDst(!std::is_signed<T>::value || is_negative) ||
+-         ux <= (std::numeric_limits<T>::max() + UnsignedDst(is_negative)) / uy;
+-}
+-
+-template <typename T, typename U, class Enable = void>
+-struct CheckedMulOp {};
+-
+-template <typename T, typename U>
+-struct CheckedMulOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename MaxExponentPromotion<T, U>::type;
+-  template <typename V>
+-  static constexpr bool Do(T x, U y, V* result) {
+-    // TODO(jschuh) Make this "constexpr if" once we're C++17.
+-    if (CheckedMulFastOp<T, U>::is_supported)
+-      return CheckedMulFastOp<T, U>::Do(x, y, result);
+-
+-    using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+-    // Verify the destination type can hold the result (always true for 0).
+-    if (BASE_NUMERICS_UNLIKELY((!IsValueInRangeForNumericType<Promotion>(x) ||
+-                                !IsValueInRangeForNumericType<Promotion>(y)) &&
+-                               x && y)) {
+-      return false;
+-    }
+-
+-    Promotion presult = {};
+-    bool is_valid = true;
+-    if (CheckedMulFastOp<Promotion, Promotion>::is_supported) {
+-      // The fast op may be available with the promoted type.
+-      is_valid = CheckedMulFastOp<Promotion, Promotion>::Do(x, y, &presult);
+-    } else if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
+-      presult = static_cast<Promotion>(x) * static_cast<Promotion>(y);
+-    } else {
+-      is_valid = CheckedMulImpl(static_cast<Promotion>(x),
+-                                static_cast<Promotion>(y), &presult);
+-    }
+-    *result = static_cast<V>(presult);
+-    return is_valid && IsValueInRangeForNumericType<V>(presult);
+-  }
+-};
+-
+-// Division just requires a check for a zero denominator or an invalid negation
+-// on signed min/-1.
+-template <typename T, typename U, class Enable = void>
+-struct CheckedDivOp {};
+-
+-template <typename T, typename U>
+-struct CheckedDivOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename MaxExponentPromotion<T, U>::type;
+-  template <typename V>
+-  static constexpr bool Do(T x, U y, V* result) {
+-    if (BASE_NUMERICS_UNLIKELY(!y))
+-      return false;
+-
+-    // The overflow check can be compiled away if we don't have the exact
+-    // combination of types needed to trigger this case.
+-    using Promotion = typename BigEnoughPromotion<T, U>::type;
+-    if (BASE_NUMERICS_UNLIKELY(
+-            (std::is_signed<T>::value && std::is_signed<U>::value &&
+-             IsTypeInRangeForNumericType<T, Promotion>::value &&
+-             static_cast<Promotion>(x) ==
+-                 std::numeric_limits<Promotion>::lowest() &&
+-             y == static_cast<U>(-1)))) {
+-      return false;
+-    }
+-
+-    // This branch always compiles away if the above branch wasn't removed.
+-    if (BASE_NUMERICS_UNLIKELY((!IsValueInRangeForNumericType<Promotion>(x) ||
+-                                !IsValueInRangeForNumericType<Promotion>(y)) &&
+-                               x)) {
+-      return false;
+-    }
+-
+-    Promotion presult = Promotion(x) / Promotion(y);
+-    *result = static_cast<V>(presult);
+-    return IsValueInRangeForNumericType<V>(presult);
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct CheckedModOp {};
+-
+-template <typename T, typename U>
+-struct CheckedModOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename MaxExponentPromotion<T, U>::type;
+-  template <typename V>
+-  static constexpr bool Do(T x, U y, V* result) {
+-    if (BASE_NUMERICS_UNLIKELY(!y))
+-      return false;
+-
+-    using Promotion = typename BigEnoughPromotion<T, U>::type;
+-    if (BASE_NUMERICS_UNLIKELY(
+-            (std::is_signed<T>::value && std::is_signed<U>::value &&
+-             IsTypeInRangeForNumericType<T, Promotion>::value &&
+-             static_cast<Promotion>(x) ==
+-                 std::numeric_limits<Promotion>::lowest() &&
+-             y == static_cast<U>(-1)))) {
+-      *result = 0;
+-      return true;
+-    }
+-
+-    Promotion presult = static_cast<Promotion>(x) % static_cast<Promotion>(y);
+-    *result = static_cast<Promotion>(presult);
+-    return IsValueInRangeForNumericType<V>(presult);
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct CheckedLshOp {};
+-
+-// Left shift. Shifts less than 0 or greater than or equal to the number
+-// of bits in the promoted type are undefined. Shifts of negative values
+-// are undefined. Otherwise it is defined when the result fits.
+-template <typename T, typename U>
+-struct CheckedLshOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = T;
+-  template <typename V>
+-  static constexpr bool Do(T x, U shift, V* result) {
+-    // Disallow negative numbers and verify the shift is in bounds.
+-    if (BASE_NUMERICS_LIKELY(!IsValueNegative(x) &&
+-                             as_unsigned(shift) <
+-                                 as_unsigned(std::numeric_limits<T>::digits))) {
+-      // Shift as unsigned to avoid undefined behavior.
+-      *result = static_cast<V>(as_unsigned(x) << shift);
+-      // If the shift can be reversed, we know it was valid.
+-      return *result >> shift == x;
+-    }
+-
+-    // Handle the legal corner-case of a full-width signed shift of zero.
+-    return std::is_signed<T>::value && !x &&
+-           as_unsigned(shift) == as_unsigned(std::numeric_limits<T>::digits);
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct CheckedRshOp {};
+-
+-// Right shift. Shifts less than 0 or greater than or equal to the number
+-// of bits in the promoted type are undefined. Otherwise, it is always defined,
+-// but a right shift of a negative value is implementation-dependent.
+-template <typename T, typename U>
+-struct CheckedRshOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = T;
+-  template <typename V>
+-  static bool Do(T x, U shift, V* result) {
+-    // Use the type conversion push negative values out of range.
+-    if (BASE_NUMERICS_LIKELY(as_unsigned(shift) <
+-                             IntegerBitsPlusSign<T>::value)) {
+-      T tmp = x >> shift;
+-      *result = static_cast<V>(tmp);
+-      return IsValueInRangeForNumericType<V>(tmp);
+-    }
+-    return false;
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct CheckedAndOp {};
+-
+-// For simplicity we support only unsigned integer results.
+-template <typename T, typename U>
+-struct CheckedAndOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename std::make_unsigned<
+-      typename MaxExponentPromotion<T, U>::type>::type;
+-  template <typename V>
+-  static constexpr bool Do(T x, U y, V* result) {
+-    result_type tmp = static_cast<result_type>(x) & static_cast<result_type>(y);
+-    *result = static_cast<V>(tmp);
+-    return IsValueInRangeForNumericType<V>(tmp);
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct CheckedOrOp {};
+-
+-// For simplicity we support only unsigned integers.
+-template <typename T, typename U>
+-struct CheckedOrOp<T,
+-                   U,
+-                   typename std::enable_if<std::is_integral<T>::value &&
+-                                           std::is_integral<U>::value>::type> {
+-  using result_type = typename std::make_unsigned<
+-      typename MaxExponentPromotion<T, U>::type>::type;
+-  template <typename V>
+-  static constexpr bool Do(T x, U y, V* result) {
+-    result_type tmp = static_cast<result_type>(x) | static_cast<result_type>(y);
+-    *result = static_cast<V>(tmp);
+-    return IsValueInRangeForNumericType<V>(tmp);
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct CheckedXorOp {};
+-
+-// For simplicity we support only unsigned integers.
+-template <typename T, typename U>
+-struct CheckedXorOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename std::make_unsigned<
+-      typename MaxExponentPromotion<T, U>::type>::type;
+-  template <typename V>
+-  static constexpr bool Do(T x, U y, V* result) {
+-    result_type tmp = static_cast<result_type>(x) ^ static_cast<result_type>(y);
+-    *result = static_cast<V>(tmp);
+-    return IsValueInRangeForNumericType<V>(tmp);
+-  }
+-};
+-
+-// Max doesn't really need to be implemented this way because it can't fail,
+-// but it makes the code much cleaner to use the MathOp wrappers.
+-template <typename T, typename U, class Enable = void>
+-struct CheckedMaxOp {};
+-
+-template <typename T, typename U>
+-struct CheckedMaxOp<
+-    T,
+-    U,
+-    typename std::enable_if<std::is_arithmetic<T>::value &&
+-                            std::is_arithmetic<U>::value>::type> {
+-  using result_type = typename MaxExponentPromotion<T, U>::type;
+-  template <typename V>
+-  static constexpr bool Do(T x, U y, V* result) {
+-    result_type tmp = IsGreater<T, U>::Test(x, y) ? static_cast<result_type>(x)
+-                                                  : static_cast<result_type>(y);
+-    *result = static_cast<V>(tmp);
+-    return IsValueInRangeForNumericType<V>(tmp);
+-  }
+-};
+-
+-// Min doesn't really need to be implemented this way because it can't fail,
+-// but it makes the code much cleaner to use the MathOp wrappers.
+-template <typename T, typename U, class Enable = void>
+-struct CheckedMinOp {};
+-
+-template <typename T, typename U>
+-struct CheckedMinOp<
+-    T,
+-    U,
+-    typename std::enable_if<std::is_arithmetic<T>::value &&
+-                            std::is_arithmetic<U>::value>::type> {
+-  using result_type = typename LowestValuePromotion<T, U>::type;
+-  template <typename V>
+-  static constexpr bool Do(T x, U y, V* result) {
+-    result_type tmp = IsLess<T, U>::Test(x, y) ? static_cast<result_type>(x)
+-                                               : static_cast<result_type>(y);
+-    *result = static_cast<V>(tmp);
+-    return IsValueInRangeForNumericType<V>(tmp);
+-  }
+-};
+-
+-// This is just boilerplate that wraps the standard floating point arithmetic.
+-// A macro isn't the nicest solution, but it beats rewriting these repeatedly.
+-#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP)                              \
+-  template <typename T, typename U>                                      \
+-  struct Checked##NAME##Op<                                              \
+-      T, U,                                                              \
+-      typename std::enable_if<std::is_floating_point<T>::value ||        \
+-                              std::is_floating_point<U>::value>::type> { \
+-    using result_type = typename MaxExponentPromotion<T, U>::type;       \
+-    template <typename V>                                                \
+-    static constexpr bool Do(T x, U y, V* result) {                      \
+-      using Promotion = typename MaxExponentPromotion<T, U>::type;       \
+-      Promotion presult = x OP y;                                        \
+-      *result = static_cast<V>(presult);                                 \
+-      return IsValueInRangeForNumericType<V>(presult);                   \
+-    }                                                                    \
+-  };
+-
+-BASE_FLOAT_ARITHMETIC_OPS(Add, +)
+-BASE_FLOAT_ARITHMETIC_OPS(Sub, -)
+-BASE_FLOAT_ARITHMETIC_OPS(Mul, *)
+-BASE_FLOAT_ARITHMETIC_OPS(Div, /)
+-
+-#undef BASE_FLOAT_ARITHMETIC_OPS
+-
+-// Floats carry around their validity state with them, but integers do not. So,
+-// we wrap the underlying value in a specialization in order to hide that detail
+-// and expose an interface via accessors.
+-enum NumericRepresentation {
+-  NUMERIC_INTEGER,
+-  NUMERIC_FLOATING,
+-  NUMERIC_UNKNOWN
+-};
+-
+-template <typename NumericType>
+-struct GetNumericRepresentation {
+-  static const NumericRepresentation value =
+-      std::is_integral<NumericType>::value
+-          ? NUMERIC_INTEGER
+-          : (std::is_floating_point<NumericType>::value ? NUMERIC_FLOATING
+-                                                        : NUMERIC_UNKNOWN);
+-};
+-
+-template <typename T,
+-          NumericRepresentation type = GetNumericRepresentation<T>::value>
+-class CheckedNumericState {};
+-
+-// Integrals require quite a bit of additional housekeeping to manage state.
+-template <typename T>
+-class CheckedNumericState<T, NUMERIC_INTEGER> {
+- private:
+-  // is_valid_ precedes value_ because member intializers in the constructors
+-  // are evaluated in field order, and is_valid_ must be read when initializing
+-  // value_.
+-  bool is_valid_;
+-  T value_;
+-
+-  // Ensures that a type conversion does not trigger undefined behavior.
+-  template <typename Src>
+-  static constexpr T WellDefinedConversionOrZero(const Src value,
+-                                                 const bool is_valid) {
+-    using SrcType = typename internal::UnderlyingType<Src>::type;
+-    return (std::is_integral<SrcType>::value || is_valid)
+-               ? static_cast<T>(value)
+-               : static_cast<T>(0);
+-  }
+-
+- public:
+-  template <typename Src, NumericRepresentation type>
+-  friend class CheckedNumericState;
+-
+-  constexpr CheckedNumericState() : is_valid_(true), value_(0) {}
+-
+-  template <typename Src>
+-  constexpr CheckedNumericState(Src value, bool is_valid)
+-      : is_valid_(is_valid && IsValueInRangeForNumericType<T>(value)),
+-        value_(WellDefinedConversionOrZero(value, is_valid_)) {
+-    static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric.");
+-  }
+-
+-  // Copy constructor.
+-  template <typename Src>
+-  constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs)
+-      : is_valid_(rhs.IsValid()),
+-        value_(WellDefinedConversionOrZero(rhs.value(), is_valid_)) {}
+-
+-  template <typename Src>
+-  constexpr explicit CheckedNumericState(Src value)
+-      : is_valid_(IsValueInRangeForNumericType<T>(value)),
+-        value_(WellDefinedConversionOrZero(value, is_valid_)) {}
+-
+-  constexpr bool is_valid() const { return is_valid_; }
+-  constexpr T value() const { return value_; }
+-};
+-
+-// Floating points maintain their own validity, but need translation wrappers.
+-template <typename T>
+-class CheckedNumericState<T, NUMERIC_FLOATING> {
+- private:
+-  T value_;
+-
+-  // Ensures that a type conversion does not trigger undefined behavior.
+-  template <typename Src>
+-  static constexpr T WellDefinedConversionOrNaN(const Src value,
+-                                                const bool is_valid) {
+-    using SrcType = typename internal::UnderlyingType<Src>::type;
+-    return (StaticDstRangeRelationToSrcRange<T, SrcType>::value ==
+-                NUMERIC_RANGE_CONTAINED ||
+-            is_valid)
+-               ? static_cast<T>(value)
+-               : std::numeric_limits<T>::quiet_NaN();
+-  }
+-
+- public:
+-  template <typename Src, NumericRepresentation type>
+-  friend class CheckedNumericState;
+-
+-  constexpr CheckedNumericState() : value_(0.0) {}
+-
+-  template <typename Src>
+-  constexpr CheckedNumericState(Src value, bool is_valid)
+-      : value_(WellDefinedConversionOrNaN(value, is_valid)) {}
+-
+-  template <typename Src>
+-  constexpr explicit CheckedNumericState(Src value)
+-      : value_(WellDefinedConversionOrNaN(
+-            value,
+-            IsValueInRangeForNumericType<T>(value))) {}
+-
+-  // Copy constructor.
+-  template <typename Src>
+-  constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs)
+-      : value_(WellDefinedConversionOrNaN(
+-            rhs.value(),
+-            rhs.is_valid() && IsValueInRangeForNumericType<T>(rhs.value()))) {}
+-
+-  constexpr bool is_valid() const {
+-    // Written this way because std::isfinite is not reliably constexpr.
+-    return MustTreatAsConstexpr(value_)
+-               ? value_ <= std::numeric_limits<T>::max() &&
+-                     value_ >= std::numeric_limits<T>::lowest()
+-               : std::isfinite(value_);
+-  }
+-  constexpr T value() const { return value_; }
+-};
+-
+-}  // namespace internal
+-}  // namespace base
+-}  // namespace pdfium
+-
+-#endif  // THIRD_PARTY_BASE_NUMERICS_CHECKED_MATH_IMPL_H_
+diff -Naur workdir/UnpackedTarball/pdfium/third_party/base/numerics/clamped_math.h workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/clamped_math.h
+--- workdir/UnpackedTarball/pdfium/third_party/base/numerics/clamped_math.h	2020-10-26 19:26:04.000000000 +0100
++++ workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/clamped_math.h	1970-01-01 01:00:00.000000000 +0100
+@@ -1,266 +0,0 @@
+-// Copyright 2017 The Chromium Authors. All rights reserved.
+-// Use of this source code is governed by a BSD-style license that can be
+-// found in the LICENSE file.
+-
+-#ifndef THIRD_PARTY_BASE_NUMERICS_CLAMPED_MATH_H_
+-#define THIRD_PARTY_BASE_NUMERICS_CLAMPED_MATH_H_
+-
+-#include <stddef.h>
+-
+-#include <limits>
+-#include <type_traits>
+-
+-#include "third_party/base/numerics/clamped_math_impl.h"
+-
+-namespace pdfium {
+-namespace base {
+-namespace internal {
+-
+-template <typename T>
+-class ClampedNumeric {
+-  static_assert(std::is_arithmetic<T>::value,
+-                "ClampedNumeric<T>: T must be a numeric type.");
+-
+- public:
+-  using type = T;
+-
+-  constexpr ClampedNumeric() : value_(0) {}
+-
+-  // Copy constructor.
+-  template <typename Src>
+-  constexpr ClampedNumeric(const ClampedNumeric<Src>& rhs)
+-      : value_(saturated_cast<T>(rhs.value_)) {}
+-
+-  template <typename Src>
+-  friend class ClampedNumeric;
+-
+-  // This is not an explicit constructor because we implicitly upgrade regular
+-  // numerics to ClampedNumerics to make them easier to use.
+-  template <typename Src>
+-  constexpr ClampedNumeric(Src value)  // NOLINT(runtime/explicit)
+-      : value_(saturated_cast<T>(value)) {
+-    static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric.");
+-  }
+-
+-  // This is not an explicit constructor because we want a seamless conversion
+-  // from StrictNumeric types.
+-  template <typename Src>
+-  constexpr ClampedNumeric(
+-      StrictNumeric<Src> value)  // NOLINT(runtime/explicit)
+-      : value_(saturated_cast<T>(static_cast<Src>(value))) {}
+-
+-  // Returns a ClampedNumeric of the specified type, cast from the current
+-  // ClampedNumeric, and saturated to the destination type.
+-  template <typename Dst>
+-  constexpr ClampedNumeric<typename UnderlyingType<Dst>::type> Cast() const {
+-    return *this;
+-  }
+-
+-  // Prototypes for the supported arithmetic operator overloads.
+-  template <typename Src>
+-  constexpr ClampedNumeric& operator+=(const Src rhs);
+-  template <typename Src>
+-  constexpr ClampedNumeric& operator-=(const Src rhs);
+-  template <typename Src>
+-  constexpr ClampedNumeric& operator*=(const Src rhs);
+-  template <typename Src>
+-  constexpr ClampedNumeric& operator/=(const Src rhs);
+-  template <typename Src>
+-  constexpr ClampedNumeric& operator%=(const Src rhs);
+-  template <typename Src>
+-  constexpr ClampedNumeric& operator<<=(const Src rhs);
+-  template <typename Src>
+-  constexpr ClampedNumeric& operator>>=(const Src rhs);
+-  template <typename Src>
+-  constexpr ClampedNumeric& operator&=(const Src rhs);
+-  template <typename Src>
+-  constexpr ClampedNumeric& operator|=(const Src rhs);
+-  template <typename Src>
+-  constexpr ClampedNumeric& operator^=(const Src rhs);
+-
+-  constexpr ClampedNumeric operator-() const {
+-    // The negation of two's complement int min is int min, so that's the
+-    // only overflow case where we will saturate.
+-    return ClampedNumeric<T>(SaturatedNegWrapper(value_));
+-  }
+-
+-  constexpr ClampedNumeric operator~() const {
+-    return ClampedNumeric<decltype(InvertWrapper(T()))>(InvertWrapper(value_));
+-  }
+-
+-  constexpr ClampedNumeric Abs() const {
+-    // The negation of two's complement int min is int min, so that's the
+-    // only overflow case where we will saturate.
+-    return ClampedNumeric<T>(SaturatedAbsWrapper(value_));
+-  }
+-
+-  template <typename U>
+-  constexpr ClampedNumeric<typename MathWrapper<ClampedMaxOp, T, U>::type> Max(
+-      const U rhs) const {
+-    using result_type = typename MathWrapper<ClampedMaxOp, T, U>::type;
+-    return ClampedNumeric<result_type>(
+-        ClampedMaxOp<T, U>::Do(value_, Wrapper<U>::value(rhs)));
+-  }
+-
+-  template <typename U>
+-  constexpr ClampedNumeric<typename MathWrapper<ClampedMinOp, T, U>::type> Min(
+-      const U rhs) const {
+-    using result_type = typename MathWrapper<ClampedMinOp, T, U>::type;
+-    return ClampedNumeric<result_type>(
+-        ClampedMinOp<T, U>::Do(value_, Wrapper<U>::value(rhs)));
+-  }
+-
+-  // This function is available only for integral types. It returns an unsigned
+-  // integer of the same width as the source type, containing the absolute value
+-  // of the source, and properly handling signed min.
+-  constexpr ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>
+-  UnsignedAbs() const {
+-    return ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>(
+-        SafeUnsignedAbs(value_));
+-  }
+-
+-  constexpr ClampedNumeric& operator++() {
+-    *this += 1;
+-    return *this;
+-  }
+-
+-  constexpr ClampedNumeric operator++(int) {
+-    ClampedNumeric value = *this;
+-    *this += 1;
+-    return value;
+-  }
+-
+-  constexpr ClampedNumeric& operator--() {
+-    *this -= 1;
+-    return *this;
+-  }
+-
+-  constexpr ClampedNumeric operator--(int) {
+-    ClampedNumeric value = *this;
+-    *this -= 1;
+-    return value;
+-  }
+-
+-  // These perform the actual math operations on the ClampedNumerics.
+-  // Binary arithmetic operations.
+-  template <template <typename, typename, typename> class M,
+-            typename L,
+-            typename R>
+-  static constexpr ClampedNumeric MathOp(const L lhs, const R rhs) {
+-    using Math = typename MathWrapper<M, L, R>::math;
+-    return ClampedNumeric<T>(
+-        Math::template Do<T>(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs)));
+-  }
+-
+-  // Assignment arithmetic operations.
+-  template <template <typename, typename, typename> class M, typename R>
+-  constexpr ClampedNumeric& MathOp(const R rhs) {
+-    using Math = typename MathWrapper<M, T, R>::math;
+-    *this =
+-        ClampedNumeric<T>(Math::template Do<T>(value_, Wrapper<R>::value(rhs)));
+-    return *this;
+-  }
+-
+-  template <typename Dst>
+-  constexpr operator Dst() const {
+-    return saturated_cast<typename ArithmeticOrUnderlyingEnum<Dst>::type>(
+-        value_);
+-  }
+-
+-  // This method extracts the raw integer value without saturating it to the
+-  // destination type as the conversion operator does. This is useful when
+-  // e.g. assigning to an auto type or passing as a deduced template parameter.
+-  constexpr T RawValue() const { return value_; }
+-
+- private:
+-  T value_;
+-
+-  // These wrappers allow us to handle state the same way for both
+-  // ClampedNumeric and POD arithmetic types.
+-  template <typename Src>
+-  struct Wrapper {
+-    static constexpr Src value(Src value) {
+-      return static_cast<typename UnderlyingType<Src>::type>(value);
+-    }
+-  };
+-};
+-
+-// Convience wrapper to return a new ClampedNumeric from the provided arithmetic
+-// or ClampedNumericType.
+-template <typename T>
+-constexpr ClampedNumeric<typename UnderlyingType<T>::type> MakeClampedNum(
+-    const T value) {
+-  return value;
+-}
+-
+-#if !BASE_NUMERICS_DISABLE_OSTREAM_OPERATORS
+-// Overload the ostream output operator to make logging work nicely.
+-template <typename T>
+-std::ostream& operator<<(std::ostream& os, const ClampedNumeric<T>& value) {
+-  os << static_cast<T>(value);
+-  return os;
+-}
+-#endif
+-
+-// These implement the variadic wrapper for the math operations.
+-template <template <typename, typename, typename> class M,
+-          typename L,
+-          typename R>
+-constexpr ClampedNumeric<typename MathWrapper<M, L, R>::type> ClampMathOp(
+-    const L lhs,
+-    const R rhs) {
+-  using Math = typename MathWrapper<M, L, R>::math;
+-  return ClampedNumeric<typename Math::result_type>::template MathOp<M>(lhs,
+-                                                                        rhs);
+-}
+-
+-// General purpose wrapper template for arithmetic operations.
+-template <template <typename, typename, typename> class M,
+-          typename L,
+-          typename R,
+-          typename... Args>
+-constexpr ClampedNumeric<typename ResultType<M, L, R, Args...>::type>
+-ClampMathOp(const L lhs, const R rhs, const Args... args) {
+-  return ClampMathOp<M>(ClampMathOp<M>(lhs, rhs), args...);
+-}
+-
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Add, +, +=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Sub, -, -=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mul, *, *=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Div, /, /=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mod, %, %=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Lsh, <<, <<=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Rsh, >>, >>=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, And, &, &=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Or, |, |=)
+-BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Xor, ^, ^=)
+-BASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Max)
+-BASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Min)
+-BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLess, <)
+-BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLessOrEqual, <=)
+-BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreater, >)
+-BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreaterOrEqual, >=)
+-BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsEqual, ==)
+-BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsNotEqual, !=)
+-
+-}  // namespace internal
+-
+-using internal::ClampedNumeric;
+-using internal::MakeClampedNum;
+-using internal::ClampMax;
+-using internal::ClampMin;
+-using internal::ClampAdd;
+-using internal::ClampSub;
+-using internal::ClampMul;
+-using internal::ClampDiv;
+-using internal::ClampMod;
+-using internal::ClampLsh;
+-using internal::ClampRsh;
+-using internal::ClampAnd;
+-using internal::ClampOr;
+-using internal::ClampXor;
+-
+-}  // namespace base
+-}  // namespace pdfium
+-
+-#endif  // THIRD_PARTY_BASE_NUMERICS_CLAMPED_MATH_H_
+diff -Naur workdir/UnpackedTarball/pdfium/third_party/base/numerics/clamped_math_impl.h workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/clamped_math_impl.h
+--- workdir/UnpackedTarball/pdfium/third_party/base/numerics/clamped_math_impl.h	2020-10-26 19:26:04.000000000 +0100
++++ workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/clamped_math_impl.h	1970-01-01 01:00:00.000000000 +0100
+@@ -1,343 +0,0 @@
+-// Copyright 2017 The Chromium Authors. All rights reserved.
+-// Use of this source code is governed by a BSD-style license that can be
+-// found in the LICENSE file.
+-
+-#ifndef THIRD_PARTY_BASE_NUMERICS_CLAMPED_MATH_IMPL_H_
+-#define THIRD_PARTY_BASE_NUMERICS_CLAMPED_MATH_IMPL_H_
+-
+-#include <stddef.h>
+-#include <stdint.h>
+-
+-#include <climits>
+-#include <cmath>
+-#include <cstdlib>
+-#include <limits>
+-#include <type_traits>
+-
+-#include "third_party/base/numerics/checked_math.h"
+-#include "third_party/base/numerics/safe_conversions.h"
+-#include "third_party/base/numerics/safe_math_shared_impl.h"
+-
+-namespace pdfium {
+-namespace base {
+-namespace internal {
+-
+-template <typename T,
+-          typename std::enable_if<std::is_integral<T>::value &&
+-                                  std::is_signed<T>::value>::type* = nullptr>
+-constexpr T SaturatedNegWrapper(T value) {
+-  return MustTreatAsConstexpr(value) || !ClampedNegFastOp<T>::is_supported
+-             ? (NegateWrapper(value) != std::numeric_limits<T>::lowest()
+-                    ? NegateWrapper(value)
+-                    : std::numeric_limits<T>::max())
+-             : ClampedNegFastOp<T>::Do(value);
+-}
+-
+-template <typename T,
+-          typename std::enable_if<std::is_integral<T>::value &&
+-                                  !std::is_signed<T>::value>::type* = nullptr>
+-constexpr T SaturatedNegWrapper(T value) {
+-  return T(0);
+-}
+-
+-template <
+-    typename T,
+-    typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
+-constexpr T SaturatedNegWrapper(T value) {
+-  return -value;
+-}
+-
+-template <typename T,
+-          typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
+-constexpr T SaturatedAbsWrapper(T value) {
+-  // The calculation below is a static identity for unsigned types, but for
+-  // signed integer types it provides a non-branching, saturated absolute value.
+-  // This works because SafeUnsignedAbs() returns an unsigned type, which can
+-  // represent the absolute value of all negative numbers of an equal-width
+-  // integer type. The call to IsValueNegative() then detects overflow in the
+-  // special case of numeric_limits<T>::min(), by evaluating the bit pattern as
+-  // a signed integer value. If it is the overflow case, we end up subtracting
+-  // one from the unsigned result, thus saturating to numeric_limits<T>::max().
+-  return static_cast<T>(SafeUnsignedAbs(value) -
+-                        IsValueNegative<T>(SafeUnsignedAbs(value)));
+-}
+-
+-template <
+-    typename T,
+-    typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
+-constexpr T SaturatedAbsWrapper(T value) {
+-  return value < 0 ? -value : value;
+-}
+-
+-template <typename T, typename U, class Enable = void>
+-struct ClampedAddOp {};
+-
+-template <typename T, typename U>
+-struct ClampedAddOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename MaxExponentPromotion<T, U>::type;
+-  template <typename V = result_type>
+-  static constexpr V Do(T x, U y) {
+-    if (ClampedAddFastOp<T, U>::is_supported)
+-      return ClampedAddFastOp<T, U>::template Do<V>(x, y);
+-
+-    static_assert(std::is_same<V, result_type>::value ||
+-                      IsTypeInRangeForNumericType<U, V>::value,
+-                  "The saturation result cannot be determined from the "
+-                  "provided types.");
+-    const V saturated = CommonMaxOrMin<V>(IsValueNegative(y));
+-    V result = {};
+-    return BASE_NUMERICS_LIKELY((CheckedAddOp<T, U>::Do(x, y, &result)))
+-               ? result
+-               : saturated;
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct ClampedSubOp {};
+-
+-template <typename T, typename U>
+-struct ClampedSubOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename MaxExponentPromotion<T, U>::type;
+-  template <typename V = result_type>
+-  static constexpr V Do(T x, U y) {
+-    // TODO(jschuh) Make this "constexpr if" once we're C++17.
+-    if (ClampedSubFastOp<T, U>::is_supported)
+-      return ClampedSubFastOp<T, U>::template Do<V>(x, y);
+-
+-    static_assert(std::is_same<V, result_type>::value ||
+-                      IsTypeInRangeForNumericType<U, V>::value,
+-                  "The saturation result cannot be determined from the "
+-                  "provided types.");
+-    const V saturated = CommonMaxOrMin<V>(!IsValueNegative(y));
+-    V result = {};
+-    return BASE_NUMERICS_LIKELY((CheckedSubOp<T, U>::Do(x, y, &result)))
+-               ? result
+-               : saturated;
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct ClampedMulOp {};
+-
+-template <typename T, typename U>
+-struct ClampedMulOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename MaxExponentPromotion<T, U>::type;
+-  template <typename V = result_type>
+-  static constexpr V Do(T x, U y) {
+-    // TODO(jschuh) Make this "constexpr if" once we're C++17.
+-    if (ClampedMulFastOp<T, U>::is_supported)
+-      return ClampedMulFastOp<T, U>::template Do<V>(x, y);
+-
+-    V result = {};
+-    const V saturated =
+-        CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y));
+-    return BASE_NUMERICS_LIKELY((CheckedMulOp<T, U>::Do(x, y, &result)))
+-               ? result
+-               : saturated;
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct ClampedDivOp {};
+-
+-template <typename T, typename U>
+-struct ClampedDivOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename MaxExponentPromotion<T, U>::type;
+-  template <typename V = result_type>
+-  static constexpr V Do(T x, U y) {
+-    V result = {};
+-    if (BASE_NUMERICS_LIKELY((CheckedDivOp<T, U>::Do(x, y, &result))))
+-      return result;
+-    // Saturation goes to max, min, or NaN (if x is zero).
+-    return x ? CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y))
+-             : SaturationDefaultLimits<V>::NaN();
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct ClampedModOp {};
+-
+-template <typename T, typename U>
+-struct ClampedModOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename MaxExponentPromotion<T, U>::type;
+-  template <typename V = result_type>
+-  static constexpr V Do(T x, U y) {
+-    V result = {};
+-    return BASE_NUMERICS_LIKELY((CheckedModOp<T, U>::Do(x, y, &result)))
+-               ? result
+-               : x;
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct ClampedLshOp {};
+-
+-// Left shift. Non-zero values saturate in the direction of the sign. A zero
+-// shifted by any value always results in zero.
+-template <typename T, typename U>
+-struct ClampedLshOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = T;
+-  template <typename V = result_type>
+-  static constexpr V Do(T x, U shift) {
+-    static_assert(!std::is_signed<U>::value, "Shift value must be unsigned.");
+-    if (BASE_NUMERICS_LIKELY(shift < std::numeric_limits<T>::digits)) {
+-      // Shift as unsigned to avoid undefined behavior.
+-      V result = static_cast<V>(as_unsigned(x) << shift);
+-      // If the shift can be reversed, we know it was valid.
+-      if (BASE_NUMERICS_LIKELY(result >> shift == x))
+-        return result;
+-    }
+-    return x ? CommonMaxOrMin<V>(IsValueNegative(x)) : 0;
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct ClampedRshOp {};
+-
+-// Right shift. Negative values saturate to -1. Positive or 0 saturates to 0.
+-template <typename T, typename U>
+-struct ClampedRshOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = T;
+-  template <typename V = result_type>
+-  static constexpr V Do(T x, U shift) {
+-    static_assert(!std::is_signed<U>::value, "Shift value must be unsigned.");
+-    // Signed right shift is odd, because it saturates to -1 or 0.
+-    const V saturated = as_unsigned(V(0)) - IsValueNegative(x);
+-    return BASE_NUMERICS_LIKELY(shift < IntegerBitsPlusSign<T>::value)
+-               ? saturated_cast<V>(x >> shift)
+-               : saturated;
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct ClampedAndOp {};
+-
+-template <typename T, typename U>
+-struct ClampedAndOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename std::make_unsigned<
+-      typename MaxExponentPromotion<T, U>::type>::type;
+-  template <typename V>
+-  static constexpr V Do(T x, U y) {
+-    return static_cast<result_type>(x) & static_cast<result_type>(y);
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct ClampedOrOp {};
+-
+-// For simplicity we promote to unsigned integers.
+-template <typename T, typename U>
+-struct ClampedOrOp<T,
+-                   U,
+-                   typename std::enable_if<std::is_integral<T>::value &&
+-                                           std::is_integral<U>::value>::type> {
+-  using result_type = typename std::make_unsigned<
+-      typename MaxExponentPromotion<T, U>::type>::type;
+-  template <typename V>
+-  static constexpr V Do(T x, U y) {
+-    return static_cast<result_type>(x) | static_cast<result_type>(y);
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct ClampedXorOp {};
+-
+-// For simplicity we support only unsigned integers.
+-template <typename T, typename U>
+-struct ClampedXorOp<T,
+-                    U,
+-                    typename std::enable_if<std::is_integral<T>::value &&
+-                                            std::is_integral<U>::value>::type> {
+-  using result_type = typename std::make_unsigned<
+-      typename MaxExponentPromotion<T, U>::type>::type;
+-  template <typename V>
+-  static constexpr V Do(T x, U y) {
+-    return static_cast<result_type>(x) ^ static_cast<result_type>(y);
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct ClampedMaxOp {};
+-
+-template <typename T, typename U>
+-struct ClampedMaxOp<
+-    T,
+-    U,
+-    typename std::enable_if<std::is_arithmetic<T>::value &&
+-                            std::is_arithmetic<U>::value>::type> {
+-  using result_type = typename MaxExponentPromotion<T, U>::type;
+-  template <typename V = result_type>
+-  static constexpr V Do(T x, U y) {
+-    return IsGreater<T, U>::Test(x, y) ? saturated_cast<V>(x)
+-                                       : saturated_cast<V>(y);
+-  }
+-};
+-
+-template <typename T, typename U, class Enable = void>
+-struct ClampedMinOp {};
+-
+-template <typename T, typename U>
+-struct ClampedMinOp<
+-    T,
+-    U,
+-    typename std::enable_if<std::is_arithmetic<T>::value &&
+-                            std::is_arithmetic<U>::value>::type> {
+-  using result_type = typename LowestValuePromotion<T, U>::type;
+-  template <typename V = result_type>
+-  static constexpr V Do(T x, U y) {
+-    return IsLess<T, U>::Test(x, y) ? saturated_cast<V>(x)
+-                                    : saturated_cast<V>(y);
+-  }
+-};
+-
+-// This is just boilerplate that wraps the standard floating point arithmetic.
+-// A macro isn't the nicest solution, but it beats rewriting these repeatedly.
+-#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP)                              \
+-  template <typename T, typename U>                                      \
+-  struct Clamped##NAME##Op<                                              \
+-      T, U,                                                              \
+-      typename std::enable_if<std::is_floating_point<T>::value ||        \
+-                              std::is_floating_point<U>::value>::type> { \
+-    using result_type = typename MaxExponentPromotion<T, U>::type;       \
+-    template <typename V = result_type>                                  \
+-    static constexpr V Do(T x, U y) {                                    \
+-      return saturated_cast<V>(x OP y);                                  \
+-    }                                                                    \
+-  };
+-
+-BASE_FLOAT_ARITHMETIC_OPS(Add, +)
+-BASE_FLOAT_ARITHMETIC_OPS(Sub, -)
+-BASE_FLOAT_ARITHMETIC_OPS(Mul, *)
+-BASE_FLOAT_ARITHMETIC_OPS(Div, /)
+-
+-#undef BASE_FLOAT_ARITHMETIC_OPS
+-
+-}  // namespace internal
+-}  // namespace base
+-}  // namespace pdfium
+-
+-#endif  // THIRD_PARTY_BASE_NUMERICS_CLAMPED_MATH_IMPL_H_
+diff -Naur workdir/UnpackedTarball/pdfium/third_party/base/numerics/safe_conversions.h workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/safe_conversions.h
+--- workdir/UnpackedTarball/pdfium/third_party/base/numerics/safe_conversions.h	2020-10-26 19:26:04.000000000 +0100
++++ workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/safe_conversions.h	2020-05-02 03:06:13.000000000 +0200
+@@ -8,21 +8,18 @@
+ #include <stddef.h>
+ 
+ #include <limits>
++#include <ostream>
+ #include <type_traits>
+ 
+ #include "third_party/base/numerics/safe_conversions_impl.h"
+ 
+-#if !defined(__native_client__) && (defined(__ARMEL__) || defined(__arch64__))
++#if defined(__ARMEL__) || defined(__arch64__)
+ #include "third_party/base/numerics/safe_conversions_arm_impl.h"
+ #define BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS (1)
+ #else
+ #define BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS (0)
+ #endif
+ 
+-#if !BASE_NUMERICS_DISABLE_OSTREAM_OPERATORS
+-#include <ostream>
+-#endif
+-
+ namespace pdfium {
+ namespace base {
+ namespace internal {
+@@ -312,14 +309,12 @@
+   return value;
+ }
+ 
+-#if !BASE_NUMERICS_DISABLE_OSTREAM_OPERATORS
+ // Overload the ostream output operator to make logging work nicely.
+ template <typename T>
+ std::ostream& operator<<(std::ostream& os, const StrictNumeric<T>& value) {
+   os << static_cast<T>(value);
+   return os;
+ }
+-#endif
+ 
+ #define BASE_NUMERIC_COMPARISON_OPERATORS(CLASS, NAME, OP)              \
+   template <typename L, typename R,                                     \
+diff -Naur workdir/UnpackedTarball/pdfium/third_party/base/numerics/safe_conversions_impl.h workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/safe_conversions_impl.h
+--- workdir/UnpackedTarball/pdfium/third_party/base/numerics/safe_conversions_impl.h	2020-10-26 19:26:04.000000000 +0100
++++ workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/safe_conversions_impl.h	2020-05-02 03:06:13.000000000 +0200
+@@ -81,9 +81,8 @@
+ constexpr typename std::make_unsigned<T>::type SafeUnsignedAbs(T value) {
+   static_assert(std::is_integral<T>::value, "Type must be integral");
+   using UnsignedT = typename std::make_unsigned<T>::type;
+-  return IsValueNegative(value)
+-             ? static_cast<UnsignedT>(0u - static_cast<UnsignedT>(value))
+-             : static_cast<UnsignedT>(value);
++  return IsValueNegative(value) ? 0 - static_cast<UnsignedT>(value)
++                                : static_cast<UnsignedT>(value);
+ }
+ 
+ // This allows us to switch paths on known compile-time constants.
+diff -Naur workdir/UnpackedTarball/pdfium/third_party/base/numerics/safe_math.h workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/safe_math.h
+--- workdir/UnpackedTarball/pdfium/third_party/base/numerics/safe_math.h	2020-10-26 19:26:04.000000000 +0100
++++ workdir/UnpackedTarball/pdfium.4137/third_party/base/numerics/safe_math.h	2020-05-02 03:06:13.000000000 +0200
+@@ -1,12 +1,510 @@
+-// Copyright 2017 The Chromium Authors. All rights reserved.
++// Copyright 2014 The Chromium Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
+ 
+ #ifndef THIRD_PARTY_BASE_NUMERICS_SAFE_MATH_H_
+ #define THIRD_PARTY_BASE_NUMERICS_SAFE_MATH_H_
+ 
+-#include "third_party/base/numerics/checked_math.h"
+-#include "third_party/base/numerics/clamped_math.h"
+-#include "third_party/base/numerics/safe_conversions.h"
++#include <stddef.h>
++
++#include <limits>
++#include <type_traits>
++
++#include "third_party/base/numerics/safe_math_impl.h"
++
++namespace pdfium {
++namespace base {
++namespace internal {
++
++// CheckedNumeric<> implements all the logic and operators for detecting integer
++// boundary conditions such as overflow, underflow, and invalid conversions.
++// The CheckedNumeric type implicitly converts from floating point and integer
++// data types, and contains overloads for basic arithmetic operations (i.e.: +,
++// -, *, / for all types and %, <<, >>, &, |, ^ for integers). Type promotions
++// are a slightly modified version of the standard C arithmetic rules with the
++// two differences being that there is no default promotion to int and bitwise
++// logical operations always return an unsigned of the wider type.
++//
++// You may also use one of the variadic convenience functions, which accept
++// standard arithmetic or CheckedNumeric types, perform arithmetic operations,
++// and return a CheckedNumeric result. The supported functions are:
++//  CheckAdd() - Addition.
++//  CheckSub() - Subtraction.
++//  CheckMul() - Multiplication.
++//  CheckDiv() - Division.
++//  CheckMod() - Modulous (integer only).
++//  CheckLsh() - Left integer shift (integer only).
++//  CheckRsh() - Right integer shift (integer only).
++//  CheckAnd() - Bitwise AND (integer only with unsigned result).
++//  CheckOr()  - Bitwise OR (integer only with unsigned result).
++//  CheckXor() - Bitwise XOR (integer only with unsigned result).
++//  CheckMax() - Maximum of supplied arguments.
++//  CheckMin() - Minimum of supplied arguments.
++//
++// The unary negation, increment, and decrement operators are supported, along
++// with the following unary arithmetic methods, which return a new
++// CheckedNumeric as a result of the operation:
++//  Abs() - Absolute value.
++//  UnsignedAbs() - Absolute value as an equal-width unsigned underlying type
++//          (valid for only integral types).
++//  Max() - Returns whichever is greater of the current instance or argument.
++//          The underlying return type is whichever has the greatest magnitude.
++//  Min() - Returns whichever is lowest of the current instance or argument.
++//          The underlying return type is whichever has can represent the lowest
++//          number in the smallest width (e.g. int8_t over unsigned, int over
++//          int8_t, and float over int).
++//
++// The following methods convert from CheckedNumeric to standard numeric values:
++//  AssignIfValid() - Assigns the underlying value to the supplied destination
++//          pointer if the value is currently valid and within the range
++//          supported by the destination type. Returns true on success.
++//  ****************************************************************************
++//  *  WARNING: All of the following functions return a StrictNumeric, which   *
++//  *  is valid for comparison and assignment operations, but will trigger a   *
++//  *  compile failure on attempts to assign to a type of insufficient range.  *
++//  ****************************************************************************
++//  IsValid() - Returns true if the underlying numeric value is valid (i.e. has
++//          has not wrapped and is not the result of an invalid conversion).
++//  ValueOrDie() - Returns the underlying value. If the state is not valid this
++//          call will crash on a CHECK.
++//  ValueOrDefault() - Returns the current value, or the supplied default if the
++//          state is not valid (will not trigger a CHECK).
++//
++// The following wrapper functions can be used to avoid the template
++// disambiguator syntax when converting a destination type.
++//   IsValidForType<>() in place of: a.template IsValid<Dst>()
++//   ValueOrDieForType<>() in place of: a.template ValueOrDie()
++//   ValueOrDefaultForType<>() in place of: a.template ValueOrDefault(default)
++//
++// The following are general utility methods that are useful for converting
++// between arithmetic types and CheckedNumeric types:
++//  CheckedNumeric::Cast<Dst>() - Instance method returning a CheckedNumeric
++//          derived from casting the current instance to a CheckedNumeric of
++//          the supplied destination type.
++//  MakeCheckedNum() - Creates a new CheckedNumeric from the underlying type of
++//          the supplied arithmetic, CheckedNumeric, or StrictNumeric type.
++//
++// Comparison operations are explicitly not supported because they could result
++// in a crash on an unexpected CHECK condition. You should use patterns like the
++// following for comparisons:
++//   CheckedNumeric<size_t> checked_size = untrusted_input_value;
++//   checked_size += HEADER LENGTH;
++//   if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size)
++//     Do stuff...
++
++template <typename T>
++class CheckedNumeric {
++  static_assert(std::is_arithmetic<T>::value,
++                "CheckedNumeric<T>: T must be a numeric type.");
++
++ public:
++  using type = T;
++
++  constexpr CheckedNumeric() = default;
++
++  // Copy constructor.
++  template <typename Src>
++  constexpr CheckedNumeric(const CheckedNumeric<Src>& rhs)
++      : state_(rhs.state_.value(), rhs.IsValid()) {}
++
++  template <typename Src>
++  friend class CheckedNumeric;
++
++  // This is not an explicit constructor because we implicitly upgrade regular
++  // numerics to CheckedNumerics to make them easier to use.
++  template <typename Src>
++  constexpr CheckedNumeric(Src value)  // NOLINT(runtime/explicit)
++      : state_(value) {
++    static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric.");
++  }
++
++  // This is not an explicit constructor because we want a seamless conversion
++  // from StrictNumeric types.
++  template <typename Src>
++  constexpr CheckedNumeric(
++      StrictNumeric<Src> value)  // NOLINT(runtime/explicit)
++      : state_(static_cast<Src>(value)) {}
++
++  // IsValid() - The public API to test if a CheckedNumeric is currently valid.
++  // A range checked destination type can be supplied using the Dst template
++  // parameter.
++  template <typename Dst = T>
++  constexpr bool IsValid() const {
++    return state_.is_valid() &&
++           IsValueInRangeForNumericType<Dst>(state_.value());
++  }
++
++  // AssignIfValid(Dst) - Assigns the underlying value if it is currently valid
++  // and is within the range supported by the destination type. Returns true if
++  // successful and false otherwise.
++  template <typename Dst>
++  constexpr bool AssignIfValid(Dst* result) const {
++    return IsValid<Dst>() ? ((*result = static_cast<Dst>(state_.value())), true)
++                          : false;
++  }
++
++  // ValueOrDie() - The primary accessor for the underlying value. If the
++  // current state is not valid it will CHECK and crash.
++  // A range checked destination type can be supplied using the Dst template
++  // parameter, which will trigger a CHECK if the value is not in bounds for
++  // the destination.
++  // The CHECK behavior can be overridden by supplying a handler as a
++  // template parameter, for test code, etc. However, the handler cannot access
++  // the underlying value, and it is not available through other means.
++  template <typename Dst = T, class CheckHandler = CheckOnFailure>
++  constexpr StrictNumeric<Dst> ValueOrDie() const {
++    return IsValid<Dst>() ? static_cast<Dst>(state_.value())
++                          : CheckHandler::template HandleFailure<Dst>();
++  }
++
++  // ValueOrDefault(T default_value) - A convenience method that returns the
++  // current value if the state is valid, and the supplied default_value for
++  // any other state.
++  // A range checked destination type can be supplied using the Dst template
++  // parameter. WARNING: This function may fail to compile or CHECK at runtime
++  // if the supplied default_value is not within range of the destination type.
++  template <typename Dst = T, typename Src>
++  constexpr StrictNumeric<Dst> ValueOrDefault(const Src default_value) const {
++    return IsValid<Dst>() ? static_cast<Dst>(state_.value())
++                          : checked_cast<Dst>(default_value);
++  }
++
++  // Returns a checked numeric of the specified type, cast from the current
++  // CheckedNumeric. If the current state is invalid or the destination cannot
++  // represent the result then the returned CheckedNumeric will be invalid.
++  template <typename Dst>
++  constexpr CheckedNumeric<typename UnderlyingType<Dst>::type> Cast() const {
++    return *this;
++  }
++
++  // This friend method is available solely for providing more detailed logging
++  // in the tests. Do not implement it in production code, because the
++  // underlying values may change at any time.
++  template <typename U>
++  friend U GetNumericValueForTest(const CheckedNumeric<U>& src);
++
++  // Prototypes for the supported arithmetic operator overloads.
++  template <typename Src>
++  CheckedNumeric& operator+=(const Src rhs);
++  template <typename Src>
++  CheckedNumeric& operator-=(const Src rhs);
++  template <typename Src>
++  CheckedNumeric& operator*=(const Src rhs);
++  template <typename Src>
++  CheckedNumeric& operator/=(const Src rhs);
++  template <typename Src>
++  CheckedNumeric& operator%=(const Src rhs);
++  template <typename Src>
++  CheckedNumeric& operator<<=(const Src rhs);
++  template <typename Src>
++  CheckedNumeric& operator>>=(const Src rhs);
++  template <typename Src>
++  CheckedNumeric& operator&=(const Src rhs);
++  template <typename Src>
++  CheckedNumeric& operator|=(const Src rhs);
++  template <typename Src>
++  CheckedNumeric& operator^=(const Src rhs);
++
++  constexpr CheckedNumeric operator-() const {
++    return CheckedNumeric<T>(
++        NegateWrapper(state_.value()),
++        IsValid() &&
++            (!std::is_signed<T>::value || std::is_floating_point<T>::value ||
++             NegateWrapper(state_.value()) !=
++                 std::numeric_limits<T>::lowest()));
++  }
++
++  constexpr CheckedNumeric operator~() const {
++    return CheckedNumeric<decltype(InvertWrapper(T()))>(
++        InvertWrapper(state_.value()), IsValid());
++  }
++
++  constexpr CheckedNumeric Abs() const {
++    return CheckedNumeric<T>(
++        AbsWrapper(state_.value()),
++        IsValid() &&
++            (!std::is_signed<T>::value || std::is_floating_point<T>::value ||
++             AbsWrapper(state_.value()) != std::numeric_limits<T>::lowest()));
++  }
++
++  template <typename U>
++  constexpr CheckedNumeric<typename MathWrapper<CheckedMaxOp, T, U>::type> Max(
++      const U rhs) const {
++    using R = typename UnderlyingType<U>::type;
++    using result_type = typename MathWrapper<CheckedMaxOp, T, U>::type;
++    // TODO(jschuh): This can be converted to the MathOp version and remain
++    // constexpr once we have C++14 support.
++    return CheckedNumeric<result_type>(
++        static_cast<result_type>(
++            IsGreater<T, R>::Test(state_.value(), Wrapper<U>::value(rhs))
++                ? state_.value()
++                : Wrapper<U>::value(rhs)),
++        state_.is_valid() && Wrapper<U>::is_valid(rhs));
++  }
++
++  template <typename U>
++  constexpr CheckedNumeric<typename MathWrapper<CheckedMinOp, T, U>::type> Min(
++      const U rhs) const {
++    using R = typename UnderlyingType<U>::type;
++    using result_type = typename MathWrapper<CheckedMinOp, T, U>::type;
++    // TODO(jschuh): This can be converted to the MathOp version and remain
++    // constexpr once we have C++14 support.
++    return CheckedNumeric<result_type>(
++        static_cast<result_type>(
++            IsLess<T, R>::Test(state_.value(), Wrapper<U>::value(rhs))
++                ? state_.value()
++                : Wrapper<U>::value(rhs)),
++        state_.is_valid() && Wrapper<U>::is_valid(rhs));
++  }
++
++  // This function is available only for integral types. It returns an unsigned
++  // integer of the same width as the source type, containing the absolute value
++  // of the source, and properly handling signed min.
++  constexpr CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>
++  UnsignedAbs() const {
++    return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>(
++        SafeUnsignedAbs(state_.value()), state_.is_valid());
++  }
++
++  CheckedNumeric& operator++() {
++    *this += 1;
++    return *this;
++  }
++
++  CheckedNumeric operator++(int) {
++    CheckedNumeric value = *this;
++    *this += 1;
++    return value;
++  }
++
++  CheckedNumeric& operator--() {
++    *this -= 1;
++    return *this;
++  }
++
++  CheckedNumeric operator--(int) {
++    CheckedNumeric value = *this;
++    *this -= 1;
++    return value;
++  }
++
++  // These perform the actual math operations on the CheckedNumerics.
++  // Binary arithmetic operations.
++  template <template <typename, typename, typename> class M,
++            typename L,
++            typename R>
++  static CheckedNumeric MathOp(const L lhs, const R rhs) {
++    using Math = typename MathWrapper<M, L, R>::math;
++    T result = 0;
++    bool is_valid =
++        Wrapper<L>::is_valid(lhs) && Wrapper<R>::is_valid(rhs) &&
++        Math::Do(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs), &result);
++    return CheckedNumeric<T>(result, is_valid);
++  }
++
++  // Assignment arithmetic operations.
++  template <template <typename, typename, typename> class M, typename R>
++  CheckedNumeric& MathOp(const R rhs) {
++    using Math = typename MathWrapper<M, T, R>::math;
++    T result = 0;  // Using T as the destination saves a range check.
++    bool is_valid = state_.is_valid() && Wrapper<R>::is_valid(rhs) &&
++                    Math::Do(state_.value(), Wrapper<R>::value(rhs), &result);
++    *this = CheckedNumeric<T>(result, is_valid);
++    return *this;
++  }
++
++ private:
++  CheckedNumericState<T> state_;
++
++  template <typename Src>
++  constexpr CheckedNumeric(Src value, bool is_valid)
++      : state_(value, is_valid) {}
++
++  // These wrappers allow us to handle state the same way for both
++  // CheckedNumeric and POD arithmetic types.
++  template <typename Src>
++  struct Wrapper {
++    static constexpr bool is_valid(Src) { return true; }
++    static constexpr Src value(Src value) { return value; }
++  };
++
++  template <typename Src>
++  struct Wrapper<CheckedNumeric<Src>> {
++    static constexpr bool is_valid(const CheckedNumeric<Src> v) {
++      return v.IsValid();
++    }
++    static constexpr Src value(const CheckedNumeric<Src> v) {
++      return v.state_.value();
++    }
++  };
++
++  template <typename Src>
++  struct Wrapper<StrictNumeric<Src>> {
++    static constexpr bool is_valid(const StrictNumeric<Src>) { return true; }
++    static constexpr Src value(const StrictNumeric<Src> v) {
++      return static_cast<Src>(v);
++    }
++  };
++};
++
++// Convenience functions to avoid the ugly template disambiguator syntax.
++template <typename Dst, typename Src>
++constexpr bool IsValidForType(const CheckedNumeric<Src> value) {
++  return value.template IsValid<Dst>();
++}
++
++template <typename Dst, typename Src>
++constexpr StrictNumeric<Dst> ValueOrDieForType(
++    const CheckedNumeric<Src> value) {
++  return value.template ValueOrDie<Dst>();
++}
++
++template <typename Dst, typename Src, typename Default>
++constexpr StrictNumeric<Dst> ValueOrDefaultForType(
++    const CheckedNumeric<Src> value,
++    const Default default_value) {
++  return value.template ValueOrDefault<Dst>(default_value);
++}
++
++// These variadic templates work out the return types.
++// TODO(jschuh): Rip all this out once we have C++14 non-trailing auto support.
++template <template <typename, typename, typename> class M,
++          typename L,
++          typename R,
++          typename... Args>
++struct ResultType;
++
++template <template <typename, typename, typename> class M,
++          typename L,
++          typename R>
++struct ResultType<M, L, R> {
++  using type = typename MathWrapper<M, L, R>::type;
++};
++
++template <template <typename, typename, typename> class M,
++          typename L,
++          typename R,
++          typename... Args>
++struct ResultType {
++  using type =
++      typename ResultType<M, typename ResultType<M, L, R>::type, Args...>::type;
++};
++
++// Convience wrapper to return a new CheckedNumeric from the provided arithmetic
++// or CheckedNumericType.
++template <typename T>
++constexpr CheckedNumeric<typename UnderlyingType<T>::type> MakeCheckedNum(
++    const T value) {
++  return value;
++}
++
++// These implement the variadic wrapper for the math operations.
++template <template <typename, typename, typename> class M,
++          typename L,
++          typename R>
++CheckedNumeric<typename MathWrapper<M, L, R>::type> ChkMathOp(const L lhs,
++                                                              const R rhs) {
++  using Math = typename MathWrapper<M, L, R>::math;
++  return CheckedNumeric<typename Math::result_type>::template MathOp<M>(lhs,
++                                                                        rhs);
++}
++
++// General purpose wrapper template for arithmetic operations.
++template <template <typename, typename, typename> class M,
++          typename L,
++          typename R,
++          typename... Args>
++CheckedNumeric<typename ResultType<M, L, R, Args...>::type>
++ChkMathOp(const L lhs, const R rhs, const Args... args) {
++  auto tmp = ChkMathOp<M>(lhs, rhs);
++  return tmp.IsValid() ? ChkMathOp<M>(tmp, args...)
++                       : decltype(ChkMathOp<M>(tmp, args...))(tmp);
++}
++
++// The following macros are just boilerplate for the standard arithmetic
++// operator overloads and variadic function templates. A macro isn't the nicest
++// solution, but it beats rewriting these over and over again.
++#define BASE_NUMERIC_ARITHMETIC_VARIADIC(NAME)                                \
++  template <typename L, typename R, typename... Args>                         \
++  CheckedNumeric<typename ResultType<Checked##NAME##Op, L, R, Args...>::type> \
++      Check##NAME(const L lhs, const R rhs, const Args... args) {             \
++    return ChkMathOp<Checked##NAME##Op, L, R, Args...>(lhs, rhs, args...);    \
++  }
++
++#define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP)               \
++  /* Binary arithmetic operator for all CheckedNumeric operations. */          \
++  template <typename L, typename R,                                            \
++            typename std::enable_if<IsCheckedOp<L, R>::value>::type* =         \
++                nullptr>                                                       \
++  CheckedNumeric<typename MathWrapper<Checked##NAME##Op, L, R>::type>          \
++  operator OP(const L lhs, const R rhs) {                                      \
++    return decltype(lhs OP rhs)::template MathOp<Checked##NAME##Op>(lhs, rhs); \
++  }                                                                            \
++  /* Assignment arithmetic operator implementation from CheckedNumeric. */     \
++  template <typename L>                                                        \
++  template <typename R>                                                        \
++  CheckedNumeric<L>& CheckedNumeric<L>::operator COMPOUND_OP(const R rhs) {    \
++    return MathOp<Checked##NAME##Op>(rhs);                                     \
++  }                                                                            \
++  /* Variadic arithmetic functions that return CheckedNumeric. */              \
++  BASE_NUMERIC_ARITHMETIC_VARIADIC(NAME)
++
++BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, +=)
++BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -=)
++BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *=)
++BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=)
++BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=)
++BASE_NUMERIC_ARITHMETIC_OPERATORS(Lsh, <<, <<=)
++BASE_NUMERIC_ARITHMETIC_OPERATORS(Rsh, >>, >>=)
++BASE_NUMERIC_ARITHMETIC_OPERATORS(And, &, &=)
++BASE_NUMERIC_ARITHMETIC_OPERATORS(Or, |, |=)
++BASE_NUMERIC_ARITHMETIC_OPERATORS(Xor, ^, ^=)
++BASE_NUMERIC_ARITHMETIC_VARIADIC(Max)
++BASE_NUMERIC_ARITHMETIC_VARIADIC(Min)
++
++#undef BASE_NUMERIC_ARITHMETIC_VARIADIC
++#undef BASE_NUMERIC_ARITHMETIC_OPERATORS
++
++// These are some extra StrictNumeric operators to support simple pointer
++// arithmetic with our result types. Since wrapping on a pointer is always
++// bad, we trigger the CHECK condition here.
++template <typename L, typename R>
++L* operator+(L* lhs, const StrictNumeric<R> rhs) {
++  uintptr_t result = CheckAdd(reinterpret_cast<uintptr_t>(lhs),
++                              CheckMul(sizeof(L), static_cast<R>(rhs)))
++                         .template ValueOrDie<uintptr_t>();
++  return reinterpret_cast<L*>(result);
++}
++
++template <typename L, typename R>
++L* operator-(L* lhs, const StrictNumeric<R> rhs) {
++  uintptr_t result = CheckSub(reinterpret_cast<uintptr_t>(lhs),
++                              CheckMul(sizeof(L), static_cast<R>(rhs)))
++                         .template ValueOrDie<uintptr_t>();
++  return reinterpret_cast<L*>(result);
++}
++
++}  // namespace internal
++
++using internal::CheckedNumeric;
++using internal::IsValidForType;
++using internal::ValueOrDieForType;
++using internal::ValueOrDefaultForType;
++using internal::MakeCheckedNum;
++using internal::CheckMax;
++using internal::CheckMin;
++using internal::CheckAdd;
++using internal::CheckSub;
++using internal::CheckMul;
++using internal::CheckDiv;
++using internal::CheckMod;
++using internal::CheckLsh;

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list