Index: components/certificate_transparency/mock_log_dns_traffic.cc |
diff --git a/components/certificate_transparency/mock_log_dns_traffic.cc b/components/certificate_transparency/mock_log_dns_traffic.cc |
index 7a616592caf4b01ebaeced556e79bb4e8c9d352f..646125bb26d670d325f3c9f35997d0ac7441d4e4 100644 |
--- a/components/certificate_transparency/mock_log_dns_traffic.cc |
+++ b/components/certificate_transparency/mock_log_dns_traffic.cc |
@@ -43,41 +43,50 @@ class DnsChangeNotifier : public net::NetworkChangeNotifier { |
// This should result in the DNS query ID always being 0. |
int FakeRandInt(int min, int max) { |
return min; |
} |
-std::vector<char> CreateDnsTxtRequest(base::StringPiece qname) { |
+bool CreateDnsTxtRequest(base::StringPiece qname, std::vector<char>* request) { |
std::string encoded_qname; |
- CHECK(net::DNSDomainFromDot(qname, &encoded_qname)); |
+ if (!net::DNSDomainFromDot(qname, &encoded_qname)) { |
+ // |qname| is an invalid domain name. |
+ return false; |
+ } |
// DNS query section: |
// N bytes - qname |
// 2 bytes - record type |
// 2 bytes - record class |
// Total = N + 4 bytes |
const size_t query_section_size = encoded_qname.size() + 4; |
- std::vector<char> request(sizeof(net::dns_protocol::Header) + |
- query_section_size); |
- base::BigEndianWriter writer(request.data(), request.size()); |
+ request->resize(sizeof(net::dns_protocol::Header) + query_section_size); |
+ base::BigEndianWriter writer(request->data(), request->size()); |
// Header |
net::dns_protocol::Header header = {}; |
header.flags = base::HostToNet16(net::dns_protocol::kFlagRD); |
header.qdcount = base::HostToNet16(1); |
- CHECK(writer.WriteBytes(&header, sizeof(header))); |
- // Query section |
- CHECK(writer.WriteBytes(encoded_qname.data(), encoded_qname.size())); |
- CHECK(writer.WriteU16(net::dns_protocol::kTypeTXT)); |
- CHECK(writer.WriteU16(net::dns_protocol::kClassIN)); |
- CHECK_EQ(0, writer.remaining()); |
- return request; |
+ if (!writer.WriteBytes(&header, sizeof(header)) || |
+ !writer.WriteBytes(encoded_qname.data(), encoded_qname.size()) || |
+ !writer.WriteU16(net::dns_protocol::kTypeTXT) || |
+ !writer.WriteU16(net::dns_protocol::kClassIN)) { |
+ return false; |
+ } |
+ |
+ if (writer.remaining() != 0) { |
+ // Less than the expected amount of data was written. |
+ return false; |
+ } |
+ |
+ return true; |
} |
-std::vector<char> CreateDnsTxtResponse(const std::vector<char>& request, |
- base::StringPiece answer) { |
+bool CreateDnsTxtResponse(const std::vector<char>& request, |
+ base::StringPiece answer, |
+ std::vector<char>* response) { |
// DNS answers section: |
// 2 bytes - qname pointer |
// 2 bytes - record type |
// 2 bytes - record class |
// 4 bytes - time-to-live |
@@ -85,44 +94,52 @@ std::vector<char> CreateDnsTxtResponse(const std::vector<char>& request, |
// N bytes - answer |
// Total = 12 + N bytes |
const size_t answers_section_size = 12 + answer.size(); |
constexpr uint32_t ttl = 86400; // seconds |
- std::vector<char> response(request.size() + answers_section_size); |
- std::copy(request.begin(), request.end(), response.begin()); |
+ response->resize(request.size() + answers_section_size); |
+ std::copy(request.begin(), request.end(), response->begin()); |
+ |
// Modify the header |
net::dns_protocol::Header* header = |
- reinterpret_cast<net::dns_protocol::Header*>(response.data()); |
+ reinterpret_cast<net::dns_protocol::Header*>(response->data()); |
header->ancount = base::HostToNet16(1); |
header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse); |
+ // The qname is at the start of the query section (just after the header). |
+ const uint8_t qname_ptr = sizeof(*header); |
+ |
// Write the answer section |
- base::BigEndianWriter writer(response.data() + request.size(), |
- response.size() - request.size()); |
- CHECK(writer.WriteU8(0xc0)); // qname is a pointer |
- CHECK(writer.WriteU8( |
- sizeof(*header))); // address of qname (start of query section) |
- CHECK(writer.WriteU16(net::dns_protocol::kTypeTXT)); |
- CHECK(writer.WriteU16(net::dns_protocol::kClassIN)); |
- CHECK(writer.WriteU32(ttl)); |
- CHECK(writer.WriteU16(answer.size())); |
- CHECK(writer.WriteBytes(answer.data(), answer.size())); |
- CHECK_EQ(0, writer.remaining()); |
+ base::BigEndianWriter writer(response->data() + request.size(), |
+ response->size() - request.size()); |
+ if (!writer.WriteU8(net::dns_protocol::kLabelPointer) || |
+ !writer.WriteU8(qname_ptr) || |
+ !writer.WriteU16(net::dns_protocol::kTypeTXT) || |
+ !writer.WriteU16(net::dns_protocol::kClassIN) || !writer.WriteU32(ttl) || |
+ !writer.WriteU16(answer.size()) || |
+ !writer.WriteBytes(answer.data(), answer.size())) { |
+ return false; |
+ } |
- return response; |
+ if (writer.remaining() != 0) { |
+ // Less than the expected amount of data was written. |
+ return false; |
+ } |
+ |
+ return true; |
} |
-std::vector<char> CreateDnsErrorResponse(const std::vector<char>& request, |
- uint8_t rcode) { |
- std::vector<char> response(request); |
+bool CreateDnsErrorResponse(const std::vector<char>& request, |
+ uint8_t rcode, |
+ std::vector<char>* response) { |
+ *response = request; |
// Modify the header |
net::dns_protocol::Header* header = |
- reinterpret_cast<net::dns_protocol::Header*>(response.data()); |
+ reinterpret_cast<net::dns_protocol::Header*>(response->data()); |
header->ancount = base::HostToNet16(1); |
header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse | rcode); |
- |
- return response; |
+ return true; |
} |
} // namespace |
// A container for all of the data needed for simulating a socket. |
@@ -185,15 +202,11 @@ class MockLogDnsTraffic::MockSocketData { |
// Encapsulates the data that is expected to be written to a socket. |
net::MockWrite expected_write_; |
// Encapsulates the data/error that should be returned when reading from a |
- // socket. The second "expected" read is a sentinel that causes socket reads |
- // beyond the first to hang until they timeout. This results in better |
- // test failure messages (rather than a CHECK-fail due to a socket read |
- // overrunning the MockRead array) and behaviour more like a real socket when |
- // an unexpected second socket read occurs. |
+ // socket. The second "expected" read is a sentinel (see |kNoMoreData|). |
net::MockRead expected_reads_[2]; |
// Holds pointers to |expected_write_| and |expected_reads_|. This is what is |
// added to net::MockClientSocketFactory to prepare a mock socket. |
net::SequencedSocketData socket_data_; |
@@ -203,58 +216,90 @@ class MockLogDnsTraffic::MockSocketData { |
MockLogDnsTraffic::MockLogDnsTraffic() : socket_read_mode_(net::ASYNC) {} |
MockLogDnsTraffic::~MockLogDnsTraffic() {} |
-void MockLogDnsTraffic::ExpectRequestAndErrorResponse(base::StringPiece qname, |
+bool MockLogDnsTraffic::ExpectRequestAndErrorResponse(base::StringPiece qname, |
uint8_t rcode) { |
- std::vector<char> request = CreateDnsTxtRequest(qname); |
- EmplaceMockSocketData(CreateDnsTxtRequest(qname), |
- CreateDnsErrorResponse(request, rcode)); |
+ std::vector<char> request; |
+ if (!CreateDnsTxtRequest(qname, &request)) { |
+ return false; |
+ } |
+ |
+ std::vector<char> response; |
+ if (!CreateDnsErrorResponse(request, rcode, &response)) { |
+ return false; |
+ } |
+ |
+ EmplaceMockSocketData(request, response); |
+ return true; |
} |
-void MockLogDnsTraffic::ExpectRequestAndSocketError(base::StringPiece qname, |
+bool MockLogDnsTraffic::ExpectRequestAndSocketError(base::StringPiece qname, |
net::Error error) { |
- EmplaceMockSocketData(CreateDnsTxtRequest(qname), error); |
+ std::vector<char> request; |
+ if (!CreateDnsTxtRequest(qname, &request)) { |
+ return false; |
+ } |
+ |
+ EmplaceMockSocketData(request, error); |
+ return true; |
} |
-void MockLogDnsTraffic::ExpectRequestAndTimeout(base::StringPiece qname) { |
- EmplaceMockSocketData(CreateDnsTxtRequest(qname)); |
+bool MockLogDnsTraffic::ExpectRequestAndTimeout(base::StringPiece qname) { |
+ std::vector<char> request; |
+ if (!CreateDnsTxtRequest(qname, &request)) { |
+ return false; |
+ } |
+ |
+ EmplaceMockSocketData(request); |
// Speed up timeout tests. |
SetDnsTimeout(TestTimeouts::tiny_timeout()); |
+ |
+ return true; |
} |
-void MockLogDnsTraffic::ExpectRequestAndResponse( |
+bool MockLogDnsTraffic::ExpectRequestAndResponse( |
base::StringPiece qname, |
const std::vector<base::StringPiece>& txt_strings) { |
std::string answer; |
for (base::StringPiece str : txt_strings) { |
// The size of the string must precede it. The size must fit into 1 byte. |
answer.insert(answer.end(), base::checked_cast<uint8_t>(str.size())); |
str.AppendToString(&answer); |
} |
- std::vector<char> request = CreateDnsTxtRequest(qname); |
- EmplaceMockSocketData(request, CreateDnsTxtResponse(request, answer)); |
+ std::vector<char> request; |
+ if (!CreateDnsTxtRequest(qname, &request)) { |
+ return false; |
+ } |
+ |
+ std::vector<char> response; |
+ if (!CreateDnsTxtResponse(request, answer, &response)) { |
+ return false; |
+ } |
+ |
+ EmplaceMockSocketData(request, response); |
+ return true; |
} |
-void MockLogDnsTraffic::ExpectLeafIndexRequestAndResponse( |
+bool MockLogDnsTraffic::ExpectLeafIndexRequestAndResponse( |
base::StringPiece qname, |
uint64_t leaf_index) { |
- ExpectRequestAndResponse(qname, { base::Uint64ToString(leaf_index) }); |
+ return ExpectRequestAndResponse(qname, {base::Uint64ToString(leaf_index)}); |
} |
-void MockLogDnsTraffic::ExpectAuditProofRequestAndResponse( |
+bool MockLogDnsTraffic::ExpectAuditProofRequestAndResponse( |
base::StringPiece qname, |
std::vector<std::string>::const_iterator audit_path_start, |
std::vector<std::string>::const_iterator audit_path_end) { |
// Join nodes in the audit path into a single string. |
std::string proof = |
std::accumulate(audit_path_start, audit_path_end, std::string()); |
- ExpectRequestAndResponse(qname, { proof }); |
+ return ExpectRequestAndResponse(qname, {proof}); |
} |
void MockLogDnsTraffic::InitializeDnsConfig() { |
net::DnsConfig dns_config; |
// Use an invalid nameserver address. This prevents the tests accidentally |