// Copyright 2021 The Crashpad Authors. All rights reserved.
//
// 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/ios/ios_intermediate_dump_reader.h"

#include <memory>
#include <stack>
#include <vector>

#include "base/logging.h"
#include "util/file/filesystem.h"
#include "util/ios/ios_intermediate_dump_data.h"
#include "util/ios/ios_intermediate_dump_format.h"
#include "util/ios/ios_intermediate_dump_list.h"
#include "util/ios/ios_intermediate_dump_object.h"
#include "util/ios/ios_intermediate_dump_writer.h"

namespace crashpad {
namespace internal {

bool IOSIntermediateDumpReader::Initialize(const base::FilePath& path) {
  ScopedFileHandle handle(LoggingOpenFileForRead(path));
  auto reader = std::make_unique<WeakFileHandleFileReader>(handle.get());

  // In the event a crash is introduced by this intermediate dump, don't ever
  // read a file twice.  To ensure this doesn't happen, immediately unlink.
  LoggingRemoveFile(path);

  // Don't initialize invalid or empty files.
  FileOffset size = LoggingFileSizeByHandle(handle.get());
  if (!handle.is_valid() || size == 0) {
    return false;
  }

  if (!Parse(reader.get(), size)) {
    LOG(ERROR) << "Intermediate dump parsing failed";
  }

  return true;
}

bool IOSIntermediateDumpReader::Parse(FileReaderInterface* reader,
                                      FileOffset file_size) {
  std::stack<IOSIntermediateDumpObject*> stack;
  stack.push(&minidump_);
  using Command = IOSIntermediateDumpWriter::CommandType;
  using Type = IOSIntermediateDumpObject::Type;

  Command command;
  if (!reader->ReadExactly(&command, sizeof(Command)) ||
      command != Command::kRootMapStart) {
    LOG(ERROR) << "Unexpected start to root map.";
    return false;
  }

  while (reader->ReadExactly(&command, sizeof(Command))) {
    IOSIntermediateDumpObject* parent = stack.top();
    switch (command) {
      case Command::kMapStart: {
        std::unique_ptr<IOSIntermediateDumpMap> new_map(
            new IOSIntermediateDumpMap());
        if (parent->GetType() == Type::kMap) {
          const auto parent_map = static_cast<IOSIntermediateDumpMap*>(parent);
          stack.push(new_map.get());
          IntermediateDumpKey key;
          if (!reader->ReadExactly(&key, sizeof(key)))
            return false;
          if (key == IntermediateDumpKey::kInvalid)
            return false;
          parent_map->map_[key] = std::move(new_map);
        } else if (parent->GetType() == Type::kList) {
          const auto parent_list =
              static_cast<IOSIntermediateDumpList*>(parent);
          stack.push(new_map.get());
          parent_list->push_back(std::move(new_map));
        } else {
          LOG(ERROR) << "Unexpected parent (not a map or list).";
          return false;
        }
        break;
      }
      case Command::kArrayStart: {
        auto new_list = std::make_unique<IOSIntermediateDumpList>();
        if (parent->GetType() != Type::kMap) {
          LOG(ERROR) << "Attempting to push an array not in a map.";
          return false;
        }

        IntermediateDumpKey key;
        if (!reader->ReadExactly(&key, sizeof(key)))
          return false;
        if (key == IntermediateDumpKey::kInvalid)
          return false;

        auto parent_map = static_cast<IOSIntermediateDumpMap*>(parent);
        stack.push(new_list.get());
        parent_map->map_[key] = std::move(new_list);
        break;
      }
      case Command::kMapEnd:
        if (stack.size() < 2) {
          LOG(ERROR) << "Attempting to pop off main map.";
          return false;
        }

        if (parent->GetType() != Type::kMap) {
          LOG(ERROR) << "Unexpected map end not in a map.";
          return false;
        }
        stack.pop();
        break;
      case Command::kArrayEnd:
        if (stack.size() < 2) {
          LOG(ERROR) << "Attempting to pop off main map.";
          return false;
        }
        if (parent->GetType() != Type::kList) {
          LOG(ERROR) << "Unexpected list end not in a list.";
          return false;
        }
        stack.pop();
        break;
      case Command::kProperty: {
        if (parent->GetType() != Type::kMap) {
          LOG(ERROR) << "Attempting to add a property not in a map.";
          return false;
        }
        IntermediateDumpKey key;
        if (!reader->ReadExactly(&key, sizeof(key)))
          return false;
        if (key == IntermediateDumpKey::kInvalid)
          return false;

        off_t value_length;
        if (!reader->ReadExactly(&value_length, sizeof(value_length))) {
          return false;
        }

        constexpr int kMaximumPropertyLength = 64 * 1024 * 1024;  // 64MB.
        if (value_length > kMaximumPropertyLength) {
          LOG(ERROR) << "Attempting to read a property that's too big: "
                     << value_length;
          return false;
        }

        std::vector<uint8_t> data(value_length);
        if (!reader->ReadExactly(data.data(), value_length)) {
          return false;
        }
        auto parent_map = static_cast<IOSIntermediateDumpMap*>(parent);
        if (parent_map->map_.find(key) != parent_map->map_.end()) {
          LOG(ERROR) << "Inserting duplicate key";
        }
        parent_map->map_[key] =
            std::make_unique<IOSIntermediateDumpData>(std::move(data));
        break;
      }
      case Command::kRootMapEnd: {
        if (stack.size() != 1) {
          LOG(ERROR) << "Unexpected end of root map.";
          return false;
        }

        if (reader->Seek(0, SEEK_CUR) != file_size) {
          LOG(ERROR) << "Root map ended before end of file.";
          return false;
        }
        return true;
      }
      default:
        LOG(ERROR) << "Failed to parse serialized intermediate minidump.";
        return false;
    }
  }

  LOG(ERROR) << "Unexpected end of root map.";
  return false;
}

}  // namespace internal
}  // namespace crashpad
