// Copyright (c) 2011 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.

// This file contains the code to apply a Courgette patch.

#include "courgette/ensemble.h"

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <utility>

#include "base/check.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/macros.h"
#include "courgette/crc.h"
#include "courgette/patcher_x86_32.h"
#include "courgette/region.h"
#include "courgette/simple_delta.h"
#include "courgette/streams.h"

namespace courgette {

// EnsemblePatchApplication is all the logic and data required to apply the
// multi-stage patch.
class EnsemblePatchApplication {
 public:
  EnsemblePatchApplication();
  ~EnsemblePatchApplication() = default;

  Status ReadHeader(SourceStream* header_stream);

  Status InitBase(const Region& region);

  Status ValidateBase();

  Status ReadInitialParameters(SourceStream* initial_parameters);

  Status PredictTransformParameters(SinkStreamSet* predicted_parameters);

  Status SubpatchTransformParameters(SinkStreamSet* prediction,
                                     SourceStream* correction,
                                     SourceStreamSet* corrected_parameters);

  Status TransformUp(SourceStreamSet* parameters,
                     SinkStreamSet* transformed_elements);

  Status SubpatchTransformedElements(SinkStreamSet* elements,
                                     SourceStream* correction,
                                     SourceStreamSet* corrected_elements);

  Status TransformDown(SourceStreamSet* transformed_elements,
                       SinkStream* basic_elements);

  Status SubpatchFinalOutput(SourceStream* original,
                             SourceStream* correction,
                             SinkStream* corrected_ensemble);

 private:
  Status SubpatchStreamSets(SinkStreamSet* predicted_items,
                            SourceStream* correction,
                            SourceStreamSet* corrected_items,
                            SinkStream* corrected_items_storage);

  Region base_region_;       // Location of in-memory copy of 'old' version.

  uint32_t source_checksum_;
  uint32_t target_checksum_;
  uint32_t final_patch_input_size_prediction_;

  std::vector<std::unique_ptr<TransformationPatcher>> patchers_;

  SinkStream corrected_parameters_storage_;
  SinkStream corrected_elements_storage_;

  DISALLOW_COPY_AND_ASSIGN(EnsemblePatchApplication);
};

EnsemblePatchApplication::EnsemblePatchApplication()
    : source_checksum_(0), target_checksum_(0),
      final_patch_input_size_prediction_(0) {
}

Status EnsemblePatchApplication::ReadHeader(SourceStream* header_stream) {
  uint32_t magic;
  if (!header_stream->ReadVarint32(&magic))
    return C_BAD_ENSEMBLE_MAGIC;

  if (magic != CourgettePatchFile::kMagic)
    return C_BAD_ENSEMBLE_MAGIC;

  uint32_t version;
  if (!header_stream->ReadVarint32(&version))
    return C_BAD_ENSEMBLE_VERSION;

  if (version != CourgettePatchFile::kVersion)
    return C_BAD_ENSEMBLE_VERSION;

  if (!header_stream->ReadVarint32(&source_checksum_))
    return C_BAD_ENSEMBLE_HEADER;

  if (!header_stream->ReadVarint32(&target_checksum_))
    return C_BAD_ENSEMBLE_HEADER;

  if (!header_stream->ReadVarint32(&final_patch_input_size_prediction_))
    return C_BAD_ENSEMBLE_HEADER;

  return C_OK;
}

Status EnsemblePatchApplication::InitBase(const Region& region) {
  base_region_.assign(region);
  return C_OK;
}

Status EnsemblePatchApplication::ValidateBase() {
  uint32_t checksum = CalculateCrc(base_region_.start(), base_region_.length());
  if (source_checksum_ != checksum)
    return C_BAD_ENSEMBLE_CRC;

  return C_OK;
}

Status EnsemblePatchApplication::ReadInitialParameters(
    SourceStream* transformation_parameters) {
  uint32_t number_of_transformations = 0;
  if (!transformation_parameters->ReadVarint32(&number_of_transformations))
    return C_BAD_ENSEMBLE_HEADER;

  for (size_t i = 0;  i < number_of_transformations;  ++i) {
    uint32_t kind;
    if (!transformation_parameters->ReadVarint32(&kind))
      return C_BAD_ENSEMBLE_HEADER;

    std::unique_ptr<TransformationPatcher> patcher;

    switch (kind) {
      case EXE_WIN_32_X86:  // Fall through.
      case EXE_ELF_32_X86:
      case EXE_WIN_32_X64:
        patcher.reset(new PatcherX86_32(base_region_));
        break;
      default:
        return C_BAD_ENSEMBLE_HEADER;
    }

    DCHECK(patcher);
    patchers_.push_back(std::move(patcher));
  }

  for (size_t i = 0;  i < patchers_.size();  ++i) {
    Status status = patchers_[i]->Init(transformation_parameters);
    if (status != C_OK)
      return status;
  }

  // All transformation_parameters should have been consumed by the above loop.
  if (!transformation_parameters->Empty())
    return C_BAD_ENSEMBLE_HEADER;

  return C_OK;
}

Status EnsemblePatchApplication::PredictTransformParameters(
    SinkStreamSet* all_predicted_parameters) {
  for (size_t i = 0;  i < patchers_.size();  ++i) {
    SinkStreamSet single_predicted_parameters;
    Status status =
        patchers_[i]->PredictTransformParameters(&single_predicted_parameters);
    if (status != C_OK)
      return status;
    if (!all_predicted_parameters->WriteSet(&single_predicted_parameters))
      return C_STREAM_ERROR;
  }
  return C_OK;
}

Status EnsemblePatchApplication::SubpatchTransformParameters(
    SinkStreamSet* predicted_parameters,
    SourceStream* correction,
    SourceStreamSet* corrected_parameters) {
  return SubpatchStreamSets(predicted_parameters,
                            correction,
                            corrected_parameters,
                            &corrected_parameters_storage_);
}

Status EnsemblePatchApplication::TransformUp(
    SourceStreamSet* parameters,
    SinkStreamSet* transformed_elements) {
  for (size_t i = 0;  i < patchers_.size();  ++i) {
    SourceStreamSet single_parameters;
    if (!parameters->ReadSet(&single_parameters))
      return C_STREAM_ERROR;
    SinkStreamSet single_transformed_element;
    Status status = patchers_[i]->Transform(&single_parameters,
                                            &single_transformed_element);
    if (status != C_OK)
      return status;
    if (!single_parameters.Empty())
      return C_STREAM_NOT_CONSUMED;
    if (!transformed_elements->WriteSet(&single_transformed_element))
      return C_STREAM_ERROR;
  }

  if (!parameters->Empty())
    return C_STREAM_NOT_CONSUMED;
  return C_OK;
}

Status EnsemblePatchApplication::SubpatchTransformedElements(
    SinkStreamSet* predicted_elements,
    SourceStream* correction,
    SourceStreamSet* corrected_elements) {
  return SubpatchStreamSets(predicted_elements,
                            correction,
                            corrected_elements,
                            &corrected_elements_storage_);
}

Status EnsemblePatchApplication::TransformDown(
    SourceStreamSet* transformed_elements,
    SinkStream* basic_elements) {
  // Construct blob of original input followed by reformed elements.

  if (!basic_elements->Reserve(final_patch_input_size_prediction_)) {
    return C_STREAM_ERROR;
  }

  // The original input:
  if (!basic_elements->Write(base_region_.start(), base_region_.length()))
    return C_STREAM_ERROR;

  for (size_t i = 0;  i < patchers_.size();  ++i) {
    SourceStreamSet single_corrected_element;
    if (!transformed_elements->ReadSet(&single_corrected_element))
      return C_STREAM_ERROR;
    Status status = patchers_[i]->Reform(&single_corrected_element,
                                         basic_elements);
    if (status != C_OK)
      return status;
    if (!single_corrected_element.Empty())
      return C_STREAM_NOT_CONSUMED;
  }

  if (!transformed_elements->Empty())
    return C_STREAM_NOT_CONSUMED;
  // We have totally consumed transformed_elements, so can free the
  // storage to which it referred.
  corrected_elements_storage_.Retire();

  return C_OK;
}

Status EnsemblePatchApplication::SubpatchFinalOutput(
    SourceStream* original,
    SourceStream* correction,
    SinkStream* corrected_ensemble) {
  Status delta_status = ApplySimpleDelta(original, correction,
                                         corrected_ensemble);
  if (delta_status != C_OK)
    return delta_status;

  if (CalculateCrc(corrected_ensemble->Buffer(),
                   corrected_ensemble->Length()) != target_checksum_)
    return C_BAD_ENSEMBLE_CRC;

  return C_OK;
}

Status EnsemblePatchApplication::SubpatchStreamSets(
    SinkStreamSet* predicted_items,
    SourceStream* correction,
    SourceStreamSet* corrected_items,
    SinkStream* corrected_items_storage) {
  SinkStream linearized_predicted_items;
  if (!predicted_items->CopyTo(&linearized_predicted_items))
    return C_STREAM_ERROR;

  SourceStream prediction;
  prediction.Init(linearized_predicted_items);

  Status status = ApplySimpleDelta(&prediction,
                                   correction,
                                   corrected_items_storage);
  if (status != C_OK)
    return status;

  if (!corrected_items->Init(corrected_items_storage->Buffer(),
                             corrected_items_storage->Length()))
    return C_STREAM_ERROR;

  return C_OK;
}

Status ApplyEnsemblePatch(SourceStream* base,
                          SourceStream* patch,
                          SinkStream* output) {
  Status status;
  EnsemblePatchApplication patch_process;

  status = patch_process.ReadHeader(patch);
  if (status != C_OK)
    return status;

  status = patch_process.InitBase(Region(base->Buffer(), base->Remaining()));
  if (status != C_OK)
    return status;

  status = patch_process.ValidateBase();
  if (status != C_OK)
    return status;

  // The rest of the patch stream is a StreamSet.
  SourceStreamSet patch_streams;
  patch_streams.Init(patch);

  SourceStream* transformation_descriptions     = patch_streams.stream(0);
  SourceStream* parameter_correction            = patch_streams.stream(1);
  SourceStream* transformed_elements_correction = patch_streams.stream(2);
  SourceStream* ensemble_correction             = patch_streams.stream(3);

  status = patch_process.ReadInitialParameters(transformation_descriptions);
  if (status != C_OK)
    return status;

  SinkStreamSet predicted_parameters;
  status = patch_process.PredictTransformParameters(&predicted_parameters);
  if (status != C_OK)
    return status;

  SourceStreamSet corrected_parameters;
  status = patch_process.SubpatchTransformParameters(&predicted_parameters,
                                                     parameter_correction,
                                                     &corrected_parameters);
  if (status != C_OK)
    return status;

  SinkStreamSet transformed_elements;
  status = patch_process.TransformUp(&corrected_parameters,
                                     &transformed_elements);
  if (status != C_OK)
    return status;

  SourceStreamSet corrected_transformed_elements;
  status = patch_process.SubpatchTransformedElements(
          &transformed_elements,
          transformed_elements_correction,
          &corrected_transformed_elements);
  if (status != C_OK)
    return status;

  SinkStream original_ensemble_and_corrected_base_elements;
  status = patch_process.TransformDown(
      &corrected_transformed_elements,
      &original_ensemble_and_corrected_base_elements);
  if (status != C_OK)
    return status;

  SourceStream final_patch_prediction;
  final_patch_prediction.Init(original_ensemble_and_corrected_base_elements);
  status = patch_process.SubpatchFinalOutput(&final_patch_prediction,
                                             ensemble_correction, output);
  if (status != C_OK)
    return status;

  return C_OK;
}

Status ApplyEnsemblePatch(base::File old_file,
                          base::File patch_file,
                          base::File new_file) {
  base::MemoryMappedFile patch_file_mem;
  if (!patch_file_mem.Initialize(std::move(patch_file)))
    return C_READ_OPEN_ERROR;

  // 'Dry-run' the first step of the patch process to validate format of header.
  SourceStream patch_header_stream;
  patch_header_stream.Init(patch_file_mem.data(), patch_file_mem.length());
  EnsemblePatchApplication patch_process;
  Status status = patch_process.ReadHeader(&patch_header_stream);
  if (status != C_OK)
    return status;

  // Read the old_file.
  base::MemoryMappedFile old_file_mem;
  if (!old_file_mem.Initialize(std::move(old_file)))
    return C_READ_ERROR;

  // Apply patch on streams.
  SourceStream old_source_stream;
  SourceStream patch_source_stream;
  old_source_stream.Init(old_file_mem.data(), old_file_mem.length());
  patch_source_stream.Init(patch_file_mem.data(), patch_file_mem.length());
  SinkStream new_sink_stream;
  status = ApplyEnsemblePatch(&old_source_stream, &patch_source_stream,
                              &new_sink_stream);
  if (status != C_OK)
    return status;

  // Write the patched data to |new_file_name|.
  int written = new_file.Write(
      0,
      reinterpret_cast<const char*>(new_sink_stream.Buffer()),
      static_cast<int>(new_sink_stream.Length()));
  if (written == -1)
    return C_WRITE_OPEN_ERROR;
  if (static_cast<size_t>(written) != new_sink_stream.Length())
    return C_WRITE_ERROR;

  return C_OK;
}

Status ApplyEnsemblePatch(const base::FilePath::CharType* old_file_name,
                          const base::FilePath::CharType* patch_file_name,
                          const base::FilePath::CharType* new_file_name) {
  Status result = ApplyEnsemblePatch(
      base::File(base::FilePath(old_file_name),
                 base::File::FLAG_OPEN | base::File::FLAG_READ |
                     base::File::FLAG_SHARE_DELETE),
      base::File(base::FilePath(patch_file_name),
                 base::File::FLAG_OPEN | base::File::FLAG_READ |
                     base::File::FLAG_SHARE_DELETE),
      base::File(base::FilePath(new_file_name),
                 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
                     base::File::FLAG_EXCLUSIVE_WRITE |
                     base::File::FLAG_SHARE_DELETE));
  if (result != C_OK)
    base::DeleteFile(base::FilePath(new_file_name));
  return result;
}

}  // namespace courgette
