Commit f5eeca03 authored by Max Moroz's avatar Max Moroz Committed by Commit Bot

[net] Add a fuzzer that tests converting a UTF16 domain name to ASCII.

Bug: 756596, 904877
Change-Id: If1f5dbefa165a3d4c50ff59c62a47e8eff5eb3c2
Reviewed-on: https://chromium-review.googlesource.com/c/1357611
Commit-Queue: Max Moroz <mmoroz@chromium.org>
Reviewed-by: default avatarEric Roman <eroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612941}
parent 4eebef5a
......@@ -2,8 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//testing/libfuzzer/fuzzer_test.gni")
import("//net/features.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
enable_built_in_dns = !is_ios && !is_proto_quic
......@@ -508,3 +508,16 @@ fuzzer_test("net_host_resolver_impl_fuzzer") {
]
dict = "//net/data/fuzzer_dictionaries/net_host_resolver_impl_fuzzer.dict"
}
if (is_win) {
fuzzer_test("net_dns_parse_domain_ascii_win_fuzzer") {
sources = [
"dns_parse_domain_ascii_win_fuzzer.cc",
]
deps = [
"//base",
"//net",
"//net:net_fuzzer_test_support",
]
}
}
......@@ -138,35 +138,6 @@ std::unique_ptr<IP_ADAPTER_ADDRESSES, base::FreeDeleter> ReadIpHelper(
return out;
}
// Converts a base::string16 domain name to ASCII, possibly using punycode.
// Returns true if the conversion succeeds and output is not empty. In case of
// failure, |domain| might become dirty.
bool ParseDomainASCII(base::StringPiece16 widestr, std::string* domain) {
DCHECK(domain);
if (widestr.empty())
return false;
// Check if already ASCII.
if (base::IsStringASCII(widestr)) {
domain->assign(widestr.begin(), widestr.end());
return true;
}
// Otherwise try to convert it from IDN to punycode.
const int kInitialBufferSize = 256;
url::RawCanonOutputT<base::char16, kInitialBufferSize> punycode;
if (!url::IDNToASCII(widestr.data(), widestr.length(), &punycode))
return false;
// |punycode_output| should now be ASCII; convert it to a std::string.
// (We could use UTF16ToASCII() instead, but that requires an extra string
// copy. Since ASCII is a subset of UTF8 the following is equivalent).
bool success = base::UTF16ToUTF8(punycode.data(), punycode.length(), domain);
DCHECK(success);
DCHECK(base::IsStringASCII(*domain));
return success && !domain->empty();
}
bool ReadDevolutionSetting(const RegistryReader& reader,
DnsSystemSettings::DevolutionSetting* setting) {
return reader.ReadDword(L"UseDomainNameDevolution", &setting->enabled) &&
......@@ -466,6 +437,32 @@ DnsSystemSettings::DnsSystemSettings()
DnsSystemSettings::~DnsSystemSettings() {
}
bool ParseDomainASCII(base::StringPiece16 widestr, std::string* domain) {
DCHECK(domain);
if (widestr.empty())
return false;
// Check if already ASCII.
if (base::IsStringASCII(widestr)) {
domain->assign(widestr.begin(), widestr.end());
return true;
}
// Otherwise try to convert it from IDN to punycode.
const int kInitialBufferSize = 256;
url::RawCanonOutputT<base::char16, kInitialBufferSize> punycode;
if (!url::IDNToASCII(widestr.data(), widestr.length(), &punycode))
return false;
// |punycode_output| should now be ASCII; convert it to a std::string.
// (We could use UTF16ToASCII() instead, but that requires an extra string
// copy. Since ASCII is a subset of UTF8 the following is equivalent).
bool success = base::UTF16ToUTF8(punycode.data(), punycode.length(), domain);
DCHECK(success);
DCHECK(base::IsStringASCII(*domain));
return success && !domain->empty();
}
bool ParseSearchList(const base::string16& value,
std::vector<std::string>* output) {
DCHECK(output);
......
......@@ -36,6 +36,12 @@ namespace net {
namespace internal {
// Converts a UTF-16 domain name to ASCII, possibly using punycode.
// Returns true if the conversion succeeds and output is not empty. In case of
// failure, |domain| might become dirty.
bool NET_EXPORT_PRIVATE ParseDomainASCII(base::StringPiece16 widestr,
std::string* domain);
// Parses |value| as search list (comma-delimited list of domain names) from
// a registry key and stores it in |out|. Returns true on success. Empty
// entries (e.g., "chromium.org,,org") terminate the list. Non-ascii hostnames
......
// Copyright 2018 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 "net/dns/dns_config_service_win.h"
#include <stddef.h>
#include <stdint.h>
#include <string>
#include "base/strings/string_piece.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
base::StringPiece16 widestr(
reinterpret_cast<const base::StringPiece16::value_type*>(data), size / 2);
std::string result;
if (net::internal::ParseDomainASCII(widestr, &result))
// Call base::ToLowerASCII to get some additional code coverage signal.
result = base::ToLowerASCII(result);
return 0;
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment