From 164049133457364ba9acb832cea392e1545ed8eb Mon Sep 17 00:00:00 2001
From: Jan Vcelak <jan.vcelak@nic.cz>
Date: Sun, 15 Nov 2015 00:11:54 +0100
Subject: [PATCH] knot_naptr_header_size: fix buffer boundary checks

found by LibFuzzer
---
 src/Makefile.am            |  1 +
 src/libknot/rrset.c        |  1 +
 src/libknot/rrtype/naptr.c | 48 ++++++++++++++++++++++++++++++++++++++
 src/libknot/rrtype/naptr.h | 35 +--------------------------
 4 files changed, 51 insertions(+), 34 deletions(-)
 create mode 100644 src/libknot/rrtype/naptr.c

diff --git a/src/Makefile.am b/src/Makefile.am
index e570beb811..341401bf56 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -113,6 +113,7 @@ libknot_la_SOURCES =				\
 	libknot/rdataset.c			\
 	libknot/rrset-dump.c			\
 	libknot/rrset.c				\
+	libknot/rrtype/naptr.c			\
 	libknot/rrtype/nsec3.c			\
 	libknot/rrtype/nsec3param.c		\
 	libknot/rrtype/opt.c			\
diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c
index 4c6184b285..212accb09d 100644
--- a/src/libknot/rrset.c
+++ b/src/libknot/rrset.c
@@ -22,6 +22,7 @@
 #include "libknot/consts.h"
 #include "libknot/descriptor.h"
 #include "libknot/dname.h"
+#include "libknot/errcode.h"
 #include "libknot/rrtype/naptr.h"
 #include "libknot/internal/mempattern.h"
 #include "libknot/internal/macros.h"
diff --git a/src/libknot/rrtype/naptr.c b/src/libknot/rrtype/naptr.c
new file mode 100644
index 0000000000..b423e28628
--- /dev/null
+++ b/src/libknot/rrtype/naptr.c
@@ -0,0 +1,48 @@
+/*  Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "libknot/errcode.h"
+#include "libknot/internal/macros.h"
+#include "libknot/internal/wire_ctx.h"
+#include "libknot/rrtype/naptr.h"
+
+_public_
+int knot_naptr_header_size(const uint8_t *naptr, const uint8_t *maxp)
+{
+	if (!naptr || !maxp || naptr > maxp) {
+		return KNOT_EINVAL;
+	}
+
+	wire_ctx_t wire = wire_ctx_init_const(naptr, maxp - naptr);
+
+	/* Fixed fields size (order, preference) */
+	wire_ctx_skip(&wire, 2 * sizeof(uint16_t));
+
+	/* Variable fields size (flags, services, regexp) */
+	for (int i = 0; i < 3; i++) {
+		uint8_t size = wire_ctx_read_u8(&wire);
+		wire_ctx_skip(&wire, size);
+	}
+
+	if (wire.error != KNOT_EOK) {
+		return KNOT_EMALF;
+	}
+
+	return wire_ctx_offset(&wire);
+}
diff --git a/src/libknot/rrtype/naptr.h b/src/libknot/rrtype/naptr.h
index b6bd36869f..f0a9ea0db1 100644
--- a/src/libknot/rrtype/naptr.h
+++ b/src/libknot/rrtype/naptr.h
@@ -13,24 +13,10 @@
     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-/*!
- * \file naptr.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- *
- * \brief Functions for manipulation of NAPTR RDATA.
- *
- * \addtogroup libknot
- * @{
- */
 
 #pragma once
 
-#include <stdbool.h>
 #include <stdint.h>
-#include <string.h>
-
-#include "libknot/errcode.h"
 
 /*!
  * \brief Counts the size of the NAPTR RDATA before the Replacement domain name.
@@ -43,23 +29,4 @@
  * \retval KNOT_EMALF if the record is malformed.
  * \retval Size of the RDATA before the Replacement domain name.
  */
-static inline int knot_naptr_header_size(const uint8_t *naptr, const uint8_t *maxp)
-{
-	int size = 0;
-
-	/* Fixed fields size (order, preference) */
-	size += 2 * sizeof(uint16_t);
-
-	/* Variable fields size (flags, services, regexp) */
-	for (int i = 0; i < 3; i++) {
-		const uint8_t *len_ptr = naptr + size;
-		if (len_ptr >= maxp) {
-			return KNOT_EMALF;
-		}
-		size += 1 + *len_ptr;
-	}
-
-	return size;
-}
-
-/*! @} */
+int knot_naptr_header_size(const uint8_t *naptr, const uint8_t *maxp);
-- 
GitLab