From d23f185ab546ace81c293249c54d723a7e4be8a0 Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
Date: Mon, 23 Mar 2026 11:26:24 -0400
Subject: [PATCH v3 1/3] Avoid Clang RISC-V auto-vectorization bug in DES

Clang 20.1.2 (and possibly earlier/later versions) miscompiles
scatter-write patterns like "array[perm[i]] = i" when compiling with
-O2. This causes incorrect DES permutation tables in
contrib/pgcrypto/crypt-des.c, resulting in wrong password hashes and
authentication failures.

Add compiler barriers (memory clobber asm statements) after scatter
writes in des_init() to prevent auto-vectorization of the affected
loops. The barriers are harmless on all compilers (GCC, Clang, MSVC) and
have negligible performance impact since DES initialization occurs only
once per connection.

The fix applies to all compilers to ensure consistent behavior and
avoid future compiler bugs with similar optimizations.
---
 contrib/pgcrypto/crypt-des.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/contrib/pgcrypto/crypt-des.c b/contrib/pgcrypto/crypt-des.c
index 98c30ea122e..0a698da7132 100644
--- a/contrib/pgcrypto/crypt-des.c
+++ b/contrib/pgcrypto/crypt-des.c
@@ -62,12 +62,14 @@
 
 #include "postgres.h"
 #include "miscadmin.h"
+#include "port/atomics.h"
 #include "port/pg_bswap.h"
 
 #include "px-crypt.h"
 
 #define _PASSWORD_EFMT1 '_'
 
+
 static const char _crypt_a64[] =
 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
@@ -265,6 +267,10 @@ des_init(void)
 	for (i = 0; i < 64; i++)
 	{
 		init_perm[final_perm[i] = IP[i] - 1] = i;
+		/* This prevents a Clang bug related to auto-vectorization */
+#if defined(__riscv) && defined(__clang__)
+		pg_memory_barrier();
+#endif
 		inv_key_perm[i] = 255;
 	}
 
@@ -276,6 +282,10 @@ des_init(void)
 	{
 		u_key_perm[i] = key_perm[i] - 1;
 		inv_key_perm[key_perm[i] - 1] = i;
+		/* This prevents a Clang bug related to auto-vectorization */
+#if defined(__riscv) && defined(__clang__)
+		pg_memory_barrier();
+#endif
 		inv_comp_perm[i] = 255;
 	}
 
@@ -283,7 +293,13 @@ des_init(void)
 	 * Invert the key compression permutation.
 	 */
 	for (i = 0; i < 48; i++)
+	{
 		inv_comp_perm[comp_perm[i] - 1] = i;
+		/* This prevents a Clang bug related to auto-vectorization */
+#if defined(__riscv) && defined(__clang__)
+		pg_memory_barrier();
+#endif
+	}
 
 	/*
 	 * Set up the OR-mask arrays for the initial and final permutations, and
@@ -353,7 +369,13 @@ des_init(void)
 	 * the output of the S-box arrays setup above.
 	 */
 	for (i = 0; i < 32; i++)
+	{
 		un_pbox[pbox[i] - 1] = i;
+		/* This prevents a Clang bug related to auto-vectorization */
+#if defined(__riscv) && defined(__clang__)
+		pg_memory_barrier();
+#endif
+	}
 
 	for (b = 0; b < 4; b++)
 		for (i = 0; i < 256; i++)
-- 
2.51.2

