From 4d1c3adfae90c829e041995d91fc28fb1b3d610e Mon Sep 17 00:00:00 2001
From: Marek Vavrusa <marek.vavrusa@nic.cz>
Date: Fri, 26 Jul 2013 15:30:41 +0200
Subject: [PATCH] Fixed skipping of multiple compr. ptrs at once.

Also correct size calculation of dname parse of compressed data.
---
 src/libknot/dname.c     | 19 ++++++++++---------
 src/libknot/util/wire.h | 10 +++++++---
 2 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/src/libknot/dname.c b/src/libknot/dname.c
index 8fc8e8ab8..682d6367f 100644
--- a/src/libknot/dname.c
+++ b/src/libknot/dname.c
@@ -50,11 +50,16 @@ knot_dname_t *knot_dname_parse(const uint8_t *pkt, size_t *pos, size_t maxpos)
 	if (parsed < 0)
 		return NULL;
 
+	/* Calculate decompressed length. */
+	int decompressed_len = knot_dname_wire_size(name, pkt);
+	if (decompressed_len < parsed)
+		return NULL;
+
 	/* Allocate space for the name. */
-	knot_dname_t *res = malloc(parsed);
+	knot_dname_t *res = malloc(decompressed_len);
 	if (res) {
 		/* Unpack name (expand compression pointers). */
-		if (knot_dname_unpack(res, name, parsed, pkt) > 0) {
+		if (knot_dname_unpack(res, name, decompressed_len, pkt) > 0) {
 			*pos += parsed;
 		} else {
 			free(res);
@@ -125,9 +130,7 @@ int knot_dname_unpack(uint8_t* dst, const knot_dname_t *src,
 		return KNOT_EINVAL;
 
 	/* Seek first real label occurence. */
-	while (knot_wire_is_pointer(src)) {
-		src = knot_wire_next_label(src, pkt);
-	}
+	src = knot_wire_seek_label(src, pkt);
 
 	/* Unpack rest of the labels. */
 	int len = 0;
@@ -570,14 +573,12 @@ int knot_dname_prefixlen(const uint8_t *name, unsigned nlabels, const uint8_t *p
 		return 1;
 
 	/* Seek first real label occurence. */
-	while (knot_wire_is_pointer(name)) {
-		name = knot_wire_next_label((uint8_t *)name, (uint8_t *)pkt);
-	}
+	name = knot_wire_seek_label(name, pkt);
 
 	int len = 1; /* Terminal label */
 	while (*name != '\0') {
 		len += *name + 1;
-		name = knot_wire_next_label((uint8_t *)name, (uint8_t *)pkt);
+		name = knot_wire_next_label(name, pkt);
 		if (--nlabels == 0) /* Count N first labels only. */
 			break;
 	}
diff --git a/src/libknot/util/wire.h b/src/libknot/util/wire.h
index 80588a689..a556636d1 100644
--- a/src/libknot/util/wire.h
+++ b/src/libknot/util/wire.h
@@ -955,10 +955,9 @@ static inline uint16_t knot_wire_get_pointer(const uint8_t *pos)
 	return (knot_wire_read_u16(pos) - KNOT_WIRE_PTR_BASE);	// Return offset.
 }
 
-static inline const uint8_t *knot_wire_next_label(const uint8_t *lp, const uint8_t *wire)
+static inline const uint8_t *knot_wire_seek_label(const uint8_t *lp, const uint8_t *wire)
 {
-	lp = lp + (lp[0] + sizeof(uint8_t));
-	if (knot_wire_is_pointer(lp)) {
+	while (knot_wire_is_pointer(lp)) {
 		if (!wire)
 			return NULL;
 		lp = wire + knot_wire_get_pointer(lp);
@@ -966,6 +965,11 @@ static inline const uint8_t *knot_wire_next_label(const uint8_t *lp, const uint8
 	return lp;
 }
 
+static inline const uint8_t *knot_wire_next_label(const uint8_t *lp, const uint8_t *wire)
+{
+	return knot_wire_seek_label(lp + (lp[0] + sizeof(uint8_t)), wire);
+}
+
 #endif /* _KNOT_WIRE_H_ */
 
 /*! @} */
-- 
GitLab