dns/dnsmessage: validate cached section when skipping sections

When skipping a section when p.resHeaderValid is set, verify
that the cached resource header is for the right section.

Fixes golang/go#62220

Change-Id: I8731dfdb5ad3cca94221b58f8be830bd2e16cff3
Reviewed-on: https://go-review.googlesource.com/c/net/+/521995
Reviewed-by: Mateusz Poliwczak <mpoliwczak34@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Damien Neil <dneil@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/dns/dnsmessage/message.go b/dns/dnsmessage/message.go
index 19ea8f1..cd997ba 100644
--- a/dns/dnsmessage/message.go
+++ b/dns/dnsmessage/message.go
@@ -619,7 +619,7 @@
 }
 
 func (p *Parser) skipResource(sec section) error {
-	if p.resHeaderValid {
+	if p.resHeaderValid && p.section == sec {
 		newOff := p.off + int(p.resHeaderLength)
 		if newOff > len(p.msg) {
 			return errResourceLen
diff --git a/dns/dnsmessage/message_test.go b/dns/dnsmessage/message_test.go
index ddb062b..1b7f3cb 100644
--- a/dns/dnsmessage/message_test.go
+++ b/dns/dnsmessage/message_test.go
@@ -1784,3 +1784,32 @@
 		t.Errorf("p.AuthorityHeader() unexpected success")
 	}
 }
+
+func TestParseWrongSection(t *testing.T) {
+	msg := smallTestMsg()
+	raw, err := msg.Pack()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var p Parser
+	if _, err := p.Start(raw); err != nil {
+		t.Fatal(err)
+	}
+
+	if err := p.SkipAllQuestions(); err != nil {
+		t.Fatalf("p.SkipAllQuestions() = %v", err)
+	}
+	if _, err := p.AnswerHeader(); err != nil {
+		t.Fatalf("p.AnswerHeader() = %v", err)
+	}
+	if _, err := p.AuthorityHeader(); err == nil {
+		t.Fatalf("p.AuthorityHeader(): unexpected success in Answer section")
+	}
+	if err := p.SkipAuthority(); err == nil {
+		t.Fatalf("p.SkipAuthority(): unexpected success in Answer section")
+	}
+	if err := p.SkipAllAuthorities(); err == nil {
+		t.Fatalf("p.SkipAllAuthorities(): unexpected success in Answer section")
+	}
+}