Possible test fault (C++)

I’m stuck on Stage #hd8 (actually I’m not stuck, details follow).

I’ve tried … adding a lot of debug info to my server and running codecrafters tests 3 times.

Here are my logs:

remote: [tester::#HD8] Connecting to 127.0.0.1:2053 using UDP
remote: [your_program] Received 33bytes
remote: [your_program] Received packet with ID 1172
remote: [your_program] Received packet with flags 0100
remote: [your_program] Received packet with QDCOUNT 1
remote: [your_program] Received packet with ANCOUNT 0
remote: [tester::#HD8] Querying: ;star-mini.c10r.facebook.com.  IN       A
remote: [tester::#HD8] Sending Request: (Messages with >>> prefix are part of this log)
remote: [tester::#HD8] >>> ;; opcode: QUERY, status: NOERROR, id: 48947
remote: [tester::#HD8] >>> ;; flags: rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
remote: [tester::#HD8] >>>
remote: [tester::#HD8] >>> ;; QUESTION SECTION:
remote: [tester::#HD8] >>> ;star-mini.c10r.facebook.com.        IN       A
remote: [tester::#HD8] >>>
remote: [your_program] Received packet with NSCOUNT 0
remote: [your_program] Received packet with ARCOUNT 0
remote: [your_program] Received 1 questions
remote: [your_program] Question 0: FQDN codecrafters.io TYPE 1 CLASS 1
remote: [your_program] Adding codecrafters.io TYPE 1 CLASS 1 TTL 60 DATA 8.8.8.8
remote: [your_program] Sending 64 bytes
remote: [your_program] 04 94 81 00 00 01 00 01 00 00 00 00 0c 63 6f 64 65 63 72 61 66 74 65 72 73 02 69 6f 00 00 01 00 01 0c 63 6f 64 65 63 72 61 66 74 65 72 73 02 69 6f 00 00 01 00 01 00 00 00 3c 00 04 08 08 08 08
remote: [your_program] Received 33bytes
remote: [your_program] Received packet with ID 48947
remote: [your_program] Received packet with flags 0100
remote: [your_program] Received packet with QDCOUNT 1
remote: [your_program] Received packet with ANCOUNT 0
remote: [your_program] Received packet with NSCOUNT 0
remote: [your_program] terminate called after throwing an instance of 'std::invalid_argument'
remote: [your_program] Received packet with ARCOUNT 0
remote: [your_program] Received 1 questions
remote: [your_program] Question 0: FQDN star-mini.c10r.facebaceb[tester::#HD8] DNS query failed: read udp 127.0.0.1:41369->127.0.0.1:2053: i/o timeout.

And here’s a snippet of my code:

std::vector<uint8_t> encodeRdata(RECORD_TYPE type, const std::string &data)
{
	std::vector<uint8_t> buf;

	switch (type)
	{
	case RECORD_TYPE::A:
	{
		uint8_t addr[4];

		if (inet_pton(AF_INET, data.c_str(), addr) != 1)
			throw std::invalid_argument("Invalid IPv4 address: " + data);

		buf.insert(buf.end(), addr, addr + 4);

		break;
	}
	case RECORD_TYPE::CNAME:
	case RECORD_TYPE::NS:
	case RECORD_TYPE::PTR:
	{
		encodeLabels(data, buf);

		break;
	}
	case RECORD_TYPE::MX:
	{
		std::istringstream in{data};
		uint16_t pref;
		std::string target;

		in >> pref >> target;
		append_u16_be(buf, pref);
		encodeLabels(target, buf);

		break;
	}
	case RECORD_TYPE::TXT:
	{
		std::istringstream in{data};
		std::string chunk;

		while (std::getline(in, chunk, ' '))
		{
			if (chunk.size() > 255)
				throw std::length_error("TXT chunk too big");

			buf.push_back(static_cast<uint8_t>(chunk.size()));
			buf.insert(buf.end(), chunk.begin(), chunk.end());
		}

		break;
	}
	default:
		std::string msg = "Unsupported RDATA type: " + to_hex16(type);
		throw std::invalid_argument(msg);
	}

	return buf;
}

So the tests were passed on my 3rd try. Second try is after I added the debug logging you see there, but the tester terminated the process early so there are some output missing.

The exception is thrown when record type is invalid. Testing it locally works well with that domain name. Also I am not hardcoding the record type, I copy it over from the client’s question section to the response’s question section.

Without changing any logic, just making my debug logging better, the third time ran it. It worked but in the 3rd run I’m unable to see that “star-mini.c10r.facebaceb” dns request in the log.

The first failed run had the domain name alt1.aspmx.l.google. com. I tried running my local test with this fqdn request and no issue.

PS: the test from this stage are weird: in my third run I only see one request for github.com the rest are all for codecrafters. io I assume there is some randomness in the FQDN requested

Hey @Mayhem93, looks like the issue is caused by reusing responseBuf (which is a bit misleadingly named, because it’s actually holding the request data).

Here’s what’s happening:

  1. Our tester first sends a codecrafters.io request (33 bytes).
  2. responseBuf gets truncated to 33 bytes.
  3. When the actual request arrives (and it’s longer than 33 bytes), no more than 33 bytes can be read into the buffer.

Let me know if you’d like further clarification!

Ah yes, good catch. My buffer variable was outside the while loop and for efficiency sake I would always resize the buff from max 512 to the actual size, hence subsequent dns responses would be malformed because I couldn’t read the whole question section.

Third run of the tests worked because the first domain name selected for the test was github. com which is shorter than the initial codecrafter .io from the prevous tests, when the longer in size domain name arrived the resize would fill the empty space with zeroes.

Also yes, very bad naming for that variable, I’ll update it.

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.