summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2014-09-18 12:09:12 +0200
committerJo-Philipp Wich <jow@openwrt.org>2014-09-18 13:58:38 +0200
commit8ea29822ce53c36c91c7b67c6a99b2c50f2c373f (patch)
tree46d6a62787924a6045a4bb1b6955527b8d09b8b2
parent10b9190c9d846ae0f9cfd0b0af3d93a99136a40a (diff)
downloadfirewall3-8ea29822ce53c36c91c7b67c6a99b2c50f2c373f.tar.gz
utils: rework fw3_bitlen2netmask() IPv6 mask calculation
The previous code wrote beyound the end of the destination buffer under certain circumstances, causing possible heap corruptions. Rewrite the IPv6 mask calculation code to use a safe byte-wise assignment loop instead of two memset() calls and one byte assignment in the middle. Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-rw-r--r--utils.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/utils.c b/utils.c
index 756633a..71a0f13 100644
--- a/utils.c
+++ b/utils.c
@@ -774,6 +774,7 @@ bool
fw3_bitlen2netmask(int family, int bits, void *mask)
{
int i;
+ uint8_t rem, b;
struct in_addr *v4;
struct in6_addr *v6;
@@ -783,18 +784,17 @@ fw3_bitlen2netmask(int family, int bits, void *mask)
return false;
v6 = mask;
- i = abs(bits);
+ rem = abs(bits);
- memset(v6->s6_addr, 0xff, i / 8);
-
- if (i < 128)
+ for (i = 0; i < sizeof(v6->s6_addr); i++)
{
- memset(v6->s6_addr + (i / 8) + 1, 0, (128 - i) / 8);
- v6->s6_addr[i / 8] = 0xff << (8 - (i & 7));
+ b = (rem > 8) ? 8 : rem;
+ v6->s6_addr[i] = (uint8_t)(0xFF << (8 - b));
+ rem -= b;
}
if (bits < 0)
- for (i = 0; i < 16; i++)
+ for (i = 0; i < sizeof(v6->s6_addr); i++)
v6->s6_addr[i] = ~v6->s6_addr[i];
}
else