From 9e8852a7c7dbc2f60fa1b9846ab684ec27db8b89 Mon Sep 17 00:00:00 2001
From: nnposter <nnposter@e0a8ed71-7df4-0310-8962-fdc924857419>
Date: Tue, 3 Sep 2019 21:56:31 +0000
Subject: [PATCH] Rectify undefined behavior of out-of-range shift op Fixes
 #1717, closes #1718

---
 CHANGELOG                 |  3 +++
 nbase/nbase_addrset.c     | 16 +++++++++-------
 ncat/test/test-addrset.sh | 19 +++++++++++++++++++
 3 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 9b0047f6c..bad75a58b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,9 @@
 #Nmap Changelog ($Id: CHANGELOG 37693 2019-07-31 18:08:34Z dmiller $); -*-text-*-

+o [GH#1717][GH#1718] Processing of IP address CIDR blocks was not working
+  correctly on ppc64, ppc64le, and s390x architectures. [rfrohl, nnposter]
+
+
 Nmap 7.80 [2019-08-01]

 o [Security][Windows] Address CVE-2019-1552 in OpenSSL by building with the prefix

diff --git a/nbase/nbase_addrset.c b/nbase/nbase_addrset.c
index 6f91bc1b2..849044e4e 100644
--- a/nbase/nbase_addrset.c
+++ b/nbase/nbase_addrset.c
@@ -477,30 +477,32 @@ static int sockaddr_to_addr(const struct sockaddr *sa, u32 *addr)

 static int sockaddr_to_mask (const struct sockaddr *sa, int bits, u32 *mask)
 {
-  s8 i;
-  int unmasked_bits = 0;
+  int i, k;
   if (bits >= 0) {
     if (sa->sa_family == AF_INET) {
-      unmasked_bits = 32 - bits;
+      bits += 96;
     }
 #ifdef HAVE_IPV6
     else if (sa->sa_family == AF_INET6) {
-      unmasked_bits = 128 - bits;
+      ; /* do nothing */
     }
 #endif
     else {
       return 0;
     }
   }
+  else
+    bits = 128;
+  k = bits / 32;
   for (i=0; i < 4; i++) {
-    if (unmasked_bits <= 32 * (3 - i)) {
+    if (i < k) {
       mask[i] = 0xffffffff;
     }
-    else if (unmasked_bits >= 32 * (4 - i)) {
+    else if (i > k) {
       mask[i] = 0;
     }
     else {
-      mask[i] = ~((1 << (unmasked_bits - (32 * (4 - i)))) - 1);
+      mask[i] = 0xfffffffe << (31 - bits % 32);
     }
   }
   return 1;
diff --git a/ncat/test/test-addrset.sh b/ncat/test/test-addrset.sh
index 7f54023c5..285c7b675 100755
--- a/ncat/test/test-addrset.sh
+++ b/ncat/test/test-addrset.sh
@@ -208,6 +208,25 @@ test_addrset "1:2::0003/120" "1:2::3 1:2::0 1:2::ff" <<EOF
 1:3::3
 EOF

+# IPv6 CIDR netmask.
+test_addrset "1:2::3:4:5/95" "1:2::3:4:5 1:2::2:0:0 1:2::3:ffff:ffff" <<EOF
+1:2::3:4:5
+1:2::1:ffff:ffff
+1:2::2:0:0
+1:2::3:ffff:ffff
+1:2::4:0:0
+1:3::3
+EOF
+
+# IPv6 CIDR netmask.
+test_addrset "11::2/15" "11::2:3:4:5 10::1 11:ffff:ffff:ffff:ffff:ffff:ffff:ffff" <<EOF
+11::2:3:4:5
+9:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+10::1
+11:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+12::0
+EOF
+
 # /128 netmask.
 test_addrset "1:2::0003/128" "1:2::3" <<EOF
 1:2::3
--
2.20.4

