diff options
author | Jo-Philipp Wich <jow@openwrt.org> | 2014-09-18 12:09:12 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jow@openwrt.org> | 2014-09-18 13:58:38 +0200 |
commit | 8ea29822ce53c36c91c7b67c6a99b2c50f2c373f (patch) | |
tree | 46d6a62787924a6045a4bb1b6955527b8d09b8b2 | |
parent | 10b9190c9d846ae0f9cfd0b0af3d93a99136a40a (diff) | |
download | firewall3-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.c | 14 |
1 files changed, 7 insertions, 7 deletions
@@ -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 |