// Copyright 2017 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/fpdfapi/parser/cpdf_read_validator.h"

#include <algorithm>
#include <utility>

#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fxcrt/fx_safe_types.h"
#include "third_party/base/notreached.h"

namespace {

constexpr FX_FILESIZE kAlignBlockValue = CPDF_Stream::kFileBufSize;

FX_FILESIZE AlignDown(FX_FILESIZE offset) {
  return offset > 0 ? (offset - offset % kAlignBlockValue) : 0;
}

FX_FILESIZE AlignUp(FX_FILESIZE offset) {
  FX_SAFE_FILESIZE safe_result = AlignDown(offset);
  safe_result += kAlignBlockValue;
  return safe_result.ValueOrDefault(offset);
}

}  // namespace

CPDF_ReadValidator::ScopedSession::ScopedSession(
    RetainPtr<CPDF_ReadValidator> validator)
    : validator_(std::move(validator)),
      saved_read_error_(validator_->read_error_),
      saved_has_unavailable_data_(validator_->has_unavailable_data_) {
  validator_->ResetErrors();
}

CPDF_ReadValidator::ScopedSession::~ScopedSession() {
  validator_->read_error_ |= saved_read_error_;
  validator_->has_unavailable_data_ |= saved_has_unavailable_data_;
}

CPDF_ReadValidator::CPDF_ReadValidator(
    const RetainPtr<IFX_SeekableReadStream>& file_read,
    CPDF_DataAvail::FileAvail* file_avail)
    : file_read_(file_read),
      file_avail_(file_avail),
      file_size_(file_read->GetSize()) {}

CPDF_ReadValidator::~CPDF_ReadValidator() = default;

void CPDF_ReadValidator::ResetErrors() {
  read_error_ = false;
  has_unavailable_data_ = false;
}

bool CPDF_ReadValidator::ReadBlockAtOffset(void* buffer,
                                           FX_FILESIZE offset,
                                           size_t size) {
  if (offset < 0) {
    NOTREACHED();
    return false;
  }

  FX_SAFE_FILESIZE end_offset = offset;
  end_offset += size;
  if (!end_offset.IsValid() || end_offset.ValueOrDie() > file_size_)
    return false;

  if (!IsDataRangeAvailable(offset, size)) {
    ScheduleDownload(offset, size);
    return false;
  }

  if (file_read_->ReadBlockAtOffset(buffer, offset, size))
    return true;

  read_error_ = true;
  ScheduleDownload(offset, size);
  return false;
}

FX_FILESIZE CPDF_ReadValidator::GetSize() {
  return file_size_;
}

void CPDF_ReadValidator::ScheduleDownload(FX_FILESIZE offset, size_t size) {
  has_unavailable_data_ = true;
  if (!hints_ || size == 0)
    return;

  const FX_FILESIZE start_segment_offset = AlignDown(offset);
  FX_SAFE_FILESIZE end_segment_offset = offset;
  end_segment_offset += size;
  if (!end_segment_offset.IsValid()) {
    NOTREACHED();
    return;
  }
  end_segment_offset =
      std::min(file_size_, AlignUp(end_segment_offset.ValueOrDie()));

  FX_SAFE_SIZE_T segment_size = end_segment_offset;
  segment_size -= start_segment_offset;
  if (!segment_size.IsValid()) {
    NOTREACHED();
    return;
  }
  hints_->AddSegment(start_segment_offset, segment_size.ValueOrDie());
}

bool CPDF_ReadValidator::IsDataRangeAvailable(FX_FILESIZE offset,
                                              size_t size) const {
  return whole_file_already_available_ || !file_avail_ ||
         file_avail_->IsDataAvail(offset, size);
}

bool CPDF_ReadValidator::IsWholeFileAvailable() {
  const FX_SAFE_SIZE_T safe_size = file_size_;
  whole_file_already_available_ =
      whole_file_already_available_ ||
      (safe_size.IsValid() && IsDataRangeAvailable(0, safe_size.ValueOrDie()));

  return whole_file_already_available_;
}

bool CPDF_ReadValidator::CheckDataRangeAndRequestIfUnavailable(
    FX_FILESIZE offset,
    size_t size) {
  if (offset > file_size_)
    return true;

  FX_SAFE_FILESIZE end_segment_offset = offset;
  end_segment_offset += size;
  // Increase checked range to allow CPDF_SyntaxParser read whole buffer.
  end_segment_offset += CPDF_Stream::kFileBufSize;
  if (!end_segment_offset.IsValid()) {
    NOTREACHED();
    return false;
  }
  end_segment_offset = std::min(
      file_size_, static_cast<FX_FILESIZE>(end_segment_offset.ValueOrDie()));
  FX_SAFE_SIZE_T segment_size = end_segment_offset;
  segment_size -= offset;
  if (!segment_size.IsValid()) {
    NOTREACHED();
    return false;
  }

  if (IsDataRangeAvailable(offset, segment_size.ValueOrDie()))
    return true;

  ScheduleDownload(offset, segment_size.ValueOrDie());
  return false;
}

bool CPDF_ReadValidator::CheckWholeFileAndRequestIfUnavailable() {
  if (IsWholeFileAvailable())
    return true;

  const FX_SAFE_SIZE_T safe_size = file_size_;
  if (safe_size.IsValid())
    ScheduleDownload(0, safe_size.ValueOrDie());

  return false;
}
