From daf0751539ea7913cb2306fbb0ba3915b474fc84 Mon Sep 17 00:00:00 2001
From: Jan Vcelak <jan.vcelak@nic.cz>
Date: Sun, 18 May 2014 17:34:05 +0200
Subject: [PATCH] sockaddr_set_raw: add check for address size

---
 src/common/sockaddr.c | 33 ++++++++++++++++++++-------------
 src/common/sockaddr.h |  8 ++++----
 2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/src/common/sockaddr.c b/src/common/sockaddr.c
index 40e23122e..eb9a13321 100644
--- a/src/common/sockaddr.c
+++ b/src/common/sockaddr.c
@@ -81,28 +81,35 @@ int sockaddr_set(struct sockaddr_storage *ss, int family, const char *straddr, i
 	return KNOT_EINVAL;
 }
 
-int sockaddr_set_raw(struct sockaddr_storage *ss, int family, const uint8_t *raw_addr)
+int sockaddr_set_raw(struct sockaddr_storage *ss, int family,
+                     const uint8_t *raw_addr, size_t raw_addr_size)
 {
 	if (ss == NULL || raw_addr == NULL) {
 		return KNOT_EINVAL;
 	}
 
-	/* Clear the structure and set family and port. */
-	memset(ss, 0, sizeof(struct sockaddr_storage));
-	ss->ss_family = family;
+	void *sa_data = NULL;
+	size_t sa_size = 0;
 
-	/* Initialize address depending on address family. */
-	if (family == AF_INET6) {
-		struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)ss;
-		memcpy(&ipv6->sin6_addr, raw_addr, sizeof(ipv6->sin6_addr));
-		return KNOT_EOK;
-	} else if (family == AF_INET) {
+	if (family == AF_INET) {
 		struct sockaddr_in *ipv4 = (struct sockaddr_in *)ss;
-		memcpy(&ipv4->sin_addr, raw_addr, sizeof(ipv4->sin_addr));
-		return KNOT_EOK;
+		sa_data = &ipv4->sin_addr;
+		sa_size = sizeof(ipv4->sin_addr);
+	} else if (family == AF_INET6) {
+		struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)ss;
+		sa_data = &ipv6->sin6_addr;
+		sa_size = sizeof(ipv6->sin6_addr);
 	}
 
-	return KNOT_EINVAL;
+	if (sa_data == NULL || sa_size != raw_addr_size) {
+		return KNOT_EINVAL;
+	}
+
+	memset(ss, 0, sizeof(*ss));
+	ss->ss_family = family;
+	memcpy(sa_data, raw_addr, sa_size);
+
+	return KNOT_EOK;
 }
 
 int sockaddr_tostr(const struct sockaddr_storage *ss, char *buf, size_t maxlen)
diff --git a/src/common/sockaddr.h b/src/common/sockaddr.h
index 3fc5a8b79..b0128d05c 100644
--- a/src/common/sockaddr.h
+++ b/src/common/sockaddr.h
@@ -79,15 +79,15 @@ int sockaddr_set(struct sockaddr_storage *ss, int family, const char *straddr, i
 /*!
  * \brief Set raw address.
  *
- * @note It is the caller's responsibility of have correct raw_addr length.
- *
  * \param ss Socket address storage.
  * \param family Address family.
- * \param addr IP address in binary format.
+ * \param raw_addr IP address in binary format.
+ * \param raw_addr_size Size of the binary address.
  *
  * return KNOT_EOK on success or an error code
  */
-int sockaddr_set_raw(struct sockaddr_storage *ss, int family, const uint8_t *raw_addr);
+int sockaddr_set_raw(struct sockaddr_storage *ss, int family,
+                     const uint8_t *raw_addr, size_t raw_addr_size);
 
 /*!
  * \brief Return string representation of socket address.
-- 
GitLab