// Copyright 2015 The Crashpad Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "util/numeric/checked_address_range.h"

#include "base/check_op.h"
#include "base/format_macros.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"

#if BUILDFLAG(IS_APPLE)
#include <mach/mach.h>
#elif BUILDFLAG(IS_WIN)
#include "util/win/address_types.h"
#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
#include "util/linux/address_types.h"
#elif BUILDFLAG(IS_FUCHSIA)
#include <zircon/types.h>
#endif  // BUILDFLAG(IS_APPLE)

namespace crashpad {
namespace internal {

template <class ValueType, class SizeType>
CheckedAddressRangeGeneric<ValueType, SizeType>::CheckedAddressRangeGeneric()
    : range_32_(0, 0),
#if defined(COMPILER_MSVC)
      range_64_(0, 0),
#endif  // COMPILER_MSVC
      is_64_bit_(false),
      range_ok_(true) {
}

template <class ValueType, class SizeType>
CheckedAddressRangeGeneric<ValueType, SizeType>::CheckedAddressRangeGeneric(
    bool is_64_bit,
    ValueType base,
    SizeType size)
#if defined(COMPILER_MSVC)
    : range_32_(0, 0),
      range_64_(0, 0)
#endif  // COMPILER_MSVC
{
  SetRange(is_64_bit, base, size);
}

template <class ValueType, class SizeType>
ValueType CheckedAddressRangeGeneric<ValueType, SizeType>::Base() const {
  return is_64_bit_ ? range_64_.base() : range_32_.base();
}

template <class ValueType, class SizeType>
SizeType CheckedAddressRangeGeneric<ValueType, SizeType>::Size() const {
  return is_64_bit_ ? range_64_.size() : range_32_.size();
}

template <class ValueType, class SizeType>
ValueType CheckedAddressRangeGeneric<ValueType, SizeType>::End() const {
  return is_64_bit_ ? range_64_.end() : range_32_.end();
}

template <class ValueType, class SizeType>
bool CheckedAddressRangeGeneric<ValueType, SizeType>::IsValid() const {
  return range_ok_ && (is_64_bit_ ? range_64_.IsValid() : range_32_.IsValid());
}

template <class ValueType, class SizeType>
void CheckedAddressRangeGeneric<ValueType, SizeType>::SetRange(bool is_64_bit,
                                                               ValueType base,
                                                               SizeType size) {
  is_64_bit_ = is_64_bit;
  if (is_64_bit_) {
    range_64_.SetRange(base, size);
    range_ok_ = true;
  } else {
    range_32_.SetRange(static_cast<uint32_t>(base),
                       static_cast<uint32_t>(size));
    range_ok_ = base::IsValueInRangeForNumericType<uint32_t>(base) &&
                base::IsValueInRangeForNumericType<uint32_t>(size);
  }
}

template <class ValueType, class SizeType>
bool CheckedAddressRangeGeneric<ValueType, SizeType>::ContainsValue(
    ValueType value) const {
  DCHECK(range_ok_);

  if (is_64_bit_) {
    return range_64_.ContainsValue(value);
  }

  if (!base::IsValueInRangeForNumericType<uint32_t>(value)) {
    return false;
  }

  return range_32_.ContainsValue(static_cast<uint32_t>(value));
}

template <class ValueType, class SizeType>
bool CheckedAddressRangeGeneric<ValueType, SizeType>::ContainsRange(
    const CheckedAddressRangeGeneric& that) const {
  DCHECK_EQ(is_64_bit_, that.is_64_bit_);
  DCHECK(range_ok_);
  DCHECK(that.range_ok_);

  return is_64_bit_ ? range_64_.ContainsRange(that.range_64_)
                    : range_32_.ContainsRange(that.range_32_);
}

template <class ValueType, class SizeType>
std::string CheckedAddressRangeGeneric<ValueType, SizeType>::AsString() const {
  return base::StringPrintf("0x%" PRIx64 " + 0x%" PRIx64 " (%s)",
                            uint64_t{Base()},
                            uint64_t{Size()},
                            Is64Bit() ? "64" : "32");
}

// Explicit instantiations for the cases we use.
#if BUILDFLAG(IS_APPLE)
template class CheckedAddressRangeGeneric<mach_vm_address_t, mach_vm_size_t>;
#elif BUILDFLAG(IS_WIN)
template class CheckedAddressRangeGeneric<WinVMAddress, WinVMSize>;
#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
template class CheckedAddressRangeGeneric<LinuxVMAddress, LinuxVMSize>;
#elif BUILDFLAG(IS_FUCHSIA)
template class CheckedAddressRangeGeneric<zx_vaddr_t, size_t>;
#endif  // BUILDFLAG(IS_APPLE)

}  // namespace internal
}  // namespace crashpad
