From 8b7b159bcc39fe17f1dab8a9692f73694e1d9a70 Mon Sep 17 00:00:00 2001
From: Ranier Vilela <ranier.vf@gmail.com>
Date: Sat, 29 Jul 2023 09:17:50 -0300
Subject: [PATCH] Avoid undefined behavior with msvc compiler. [1] msvc
 documentation says: [out] Loaded with the bit position of the first set bit 
 (1) found. Otherwise, undefined.

_BitScanReverse and _BitScanReverse64 really need check return value.
Because both can functions fails in search of bit index.

More with msvc compiler the current implementation lacks assertion checks
the input parameter.

Author: Ranier Vilela (ranier.vf@gmail.com)

[1] https://learn.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64?view=msvc-170
---
 src/include/port/pg_bitutils.h | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h
index 21a4fa0341..d285fb83ec 100644
--- a/src/include/port/pg_bitutils.h
+++ b/src/include/port/pg_bitutils.h
@@ -46,11 +46,15 @@ pg_leftmost_one_pos32(uint32 word)
 	return 31 - __builtin_clz(word);
 #elif defined(_MSC_VER)
 	unsigned long result;
-	bool		non_zero;
+	unsigned char is_non_zero;
 
-	non_zero = _BitScanReverse(&result, word);
-	Assert(non_zero);
-	return (int) result;
+	Assert(word != 0);
+
+	is_non_zero = _BitScanReverse(&result, word);
+	if (is_non_zero)
+		return (int) result;
+	else
+		return 0;
 #else
 	int			shift = 32 - 8;
 
@@ -83,11 +87,15 @@ pg_leftmost_one_pos64(uint64 word)
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
-	bool		non_zero;
+	unsigned char is_non_zero;
 
-	non_zero = _BitScanReverse64(&result, word);
-	Assert(non_zero);
-	return (int) result;
+	Assert(word != 0);
+
+	is_non_zero = _BitScanReverse64(&result, word);
+	if (is_non_zero)
+		return (int) result;
+	else
+		return 0;
 #else
 	int			shift = 64 - 8;
 
-- 
2.32.0.windows.1

