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

#include <algorithm>
#include <sstream>
#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/json/json_reader.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "base/values.h"
#include "net/base/address_list.h"
#include "net/base/dns_util.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/dns_query.h"
#include "net/dns/dns_response.h"

namespace {

void CrashDoubleFree(void) {
  // Cause ASAN to detect a double-free
  void *p = malloc(1);
  LOG(INFO) << "Allocated p=" << p << ".  Double-freeing...";
  free(p);
  free(p);
}

void CrashNullPointerDereference(void) {
  // Cause the program to segfault with a NULL pointer dereference
  int *p = NULL;
  *p = 0;
}

bool FitsUint8(int num) {
  return (num >= 0) && (num <= kuint8max);
}

bool FitsUint16(int num) {
  return (num >= 0) && (num <= kuint16max);
}

bool ReadTestCase(const char* filename,
                  uint16* id, std::string* qname, uint16* qtype,
                  std::vector<char>* resp_buf,
                  bool* crash_test) {
  base::FilePath filepath = base::FilePath::FromUTF8Unsafe(filename);

  std::string json;
  if (!base::ReadFileToString(filepath, &json)) {
    LOG(ERROR) << filename << ": couldn't read file.";
    return false;
  }

  scoped_ptr<base::Value> value(base::JSONReader::Read(json));
  if (!value.get()) {
    LOG(ERROR) << filename << ": couldn't parse JSON.";
    return false;
  }

  base::DictionaryValue* dict;
  if (!value->GetAsDictionary(&dict)) {
    LOG(ERROR) << filename << ": test case is not a dictionary.";
    return false;
  }

  *crash_test = dict->HasKey("crash_test");
  if (*crash_test) {
    LOG(INFO) << filename << ": crash_test is set!";
    return true;
  }

  int id_int;
  if (!dict->GetInteger("id", &id_int)) {
    LOG(ERROR) << filename << ": id is missing or not an integer.";
    return false;
  }
  if (!FitsUint16(id_int)) {
    LOG(ERROR) << filename << ": id is out of range.";
    return false;
  }
  *id = static_cast<uint16>(id_int);

  if (!dict->GetStringASCII("qname", qname)) {
    LOG(ERROR) << filename << ": qname is missing or not a string.";
    return false;
  }

  int qtype_int;
  if (!dict->GetInteger("qtype", &qtype_int)) {
    LOG(ERROR) << filename << ": qtype is missing or not an integer.";
    return false;
  }
  if (!FitsUint16(qtype_int)) {
    LOG(ERROR) << filename << ": qtype is out of range.";
    return false;
  }
  *qtype = static_cast<uint16>(qtype_int);

  base::ListValue* resp_list;
  if (!dict->GetList("response", &resp_list)) {
    LOG(ERROR) << filename << ": response is missing or not a list.";
    return false;
  }

  size_t resp_size = resp_list->GetSize();
  resp_buf->clear();
  resp_buf->reserve(resp_size);
  for (size_t i = 0; i < resp_size; i++) {
    int resp_byte_int;
    if ((!resp_list->GetInteger(i, &resp_byte_int))) {
      LOG(ERROR) << filename << ": response[" << i << "] is not an integer.";
      return false;
    }
    if (!FitsUint8(resp_byte_int)) {
      LOG(ERROR) << filename << ": response[" << i << "] is out of range.";
      return false;
    }
    resp_buf->push_back(static_cast<char>(resp_byte_int));
  }
  DCHECK(resp_buf->size() == resp_size);

  LOG(INFO) << "Query: id=" << id_int << ", "
            << "qname=" << *qname << ", "
            << "qtype=" << qtype_int << ", "
            << "resp_size=" << resp_size;

  return true;
}

void RunTestCase(uint16 id, std::string& qname, uint16 qtype,
                 std::vector<char>& resp_buf) {
  net::DnsQuery query(id, qname, qtype);
  net::DnsResponse response;
  std::copy(resp_buf.begin(), resp_buf.end(), response.io_buffer()->data());

  if (!response.InitParse(resp_buf.size(), query)) {
    LOG(INFO) << "InitParse failed.";
    return;
  }

  net::AddressList address_list;
  base::TimeDelta ttl;
  net::DnsResponse::Result result = response.ParseToAddressList(
      &address_list, &ttl);
  if (result != net::DnsResponse::DNS_PARSE_OK) {
    LOG(INFO) << "ParseToAddressList failed: " << result;
    return;
  }

  // Print the response in one compact line.
  std::stringstream result_line;
  result_line << "Response: address_list={ ";
  for (unsigned int i = 0; i < address_list.size(); i++)
    result_line << address_list[i].ToString() << " ";
  result_line << "}, ttl=" << ttl.InSeconds() << "s";

  LOG(INFO) << result_line.str();
}

bool ReadAndRunTestCase(const char* filename) {
  uint16 id = 0;
  std::string qname;
  uint16 qtype = 0;
  std::vector<char> resp_buf;
  bool crash_test = false;

  LOG(INFO) << "Test case: " << filename;

  // ReadTestCase will print a useful error message if it fails.
  if (!ReadTestCase(filename, &id, &qname, &qtype, &resp_buf, &crash_test))
    return false;

  if (crash_test) {
    LOG(INFO) << "Crashing.";
    CrashDoubleFree();
    // if we're not running under ASAN, that might not have worked
    CrashNullPointerDereference();
    NOTREACHED();
    return true;
  }

  std::string qname_dns;
  if (!net::DNSDomainFromDot(qname, &qname_dns)) {
    LOG(ERROR) << filename << ": DNSDomainFromDot(" << qname << ") failed.";
    return false;
  }

  RunTestCase(id, qname_dns, qtype, resp_buf);

  return true;
}

}

int main(int argc, char** argv) {
  int ret = 0;

  for (int i = 1; i < argc; i++)
    if (!ReadAndRunTestCase(argv[i]))
      ret = 2;

  // Cluster-Fuzz likes "#EOF" as the last line of output to help distinguish
  // successful runs from crashes.
  printf("#EOF\n");

  return ret;
}

