From fa56bf1488dbb1f6555e61dc385330d740cbf33b Mon Sep 17 00:00:00 2001 From: Bill Chung Date: Thu, 1 May 2025 21:28:36 +0800 Subject: [PATCH 1/3] Issue #1080: Replace the original usage of string.GetHashCode() with hash value calculation using the MurmurHash algorithm. --- src/NetMQ/Core/Transports/Ipc/IpcAddress.cs | 55 ++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs b/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs index 2ccf12484..9b635cd07 100644 --- a/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs +++ b/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs @@ -39,7 +39,7 @@ public void Resolve(string name, bool ip4Only) { m_name = name; - int hash = name.GetHashCode(); + int hash = GetMurmurHash(name); if (hash < 0) hash = -hash; hash = hash%55536; @@ -48,6 +48,59 @@ public void Resolve(string name, bool ip4Only) this.Address = new IPEndPoint(IPAddress.Loopback, hash); } + /// + /// Calculate hash values using the MurmurHash algorithm + /// + /// input + /// hash value + private static int GetMurmurHash(string name) + { + const uint seed = 0xc58f1a7b; + const uint m = 0x5bd1e995; + const int r = 24; + + uint hash = seed ^ (uint)name.Length; + int length = name.Length; + int currentIndex = 0; + + while (length >= 4) + { + uint k = (uint)(name[currentIndex] | + (name[currentIndex + 1] << 8) | + (name[currentIndex + 2] << 16) | + (name[currentIndex + 3] << 24)); + + k *= m; + k ^= k >> r; + k *= m; + + hash *= m; + hash ^= k; + + currentIndex += 4; + length -= 4; + } + + switch (length) + { + case 3: + hash ^= (uint)(name[currentIndex + 2] << 16); + goto case 2; + case 2: + hash ^= (uint)(name[currentIndex + 1] << 8); + goto case 1; + case 1: + hash ^= name[currentIndex]; + hash *= m; + break; + } + + hash ^= hash >> 13; + hash *= m; + hash ^= hash >> 15; + return (int)hash; + } + [DisallowNull] public IPEndPoint? Address { get; private set; } From d9784a8c88e6a8c76da7ca57fcdf1bc545069bc7 Mon Sep 17 00:00:00 2001 From: Bill Chung Date: Wed, 7 May 2025 21:33:03 +0800 Subject: [PATCH 2/3] modify hash type from int to uint --- src/NetMQ/Core/Transports/Ipc/IpcAddress.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs b/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs index 9b635cd07..c489ba703 100644 --- a/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs +++ b/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs @@ -39,13 +39,10 @@ public void Resolve(string name, bool ip4Only) { m_name = name; - int hash = GetMurmurHash(name); - if (hash < 0) - hash = -hash; - hash = hash%55536; - hash += 10000; - - this.Address = new IPEndPoint(IPAddress.Loopback, hash); + uint hash = GetMurmurHash(name); + int port = (int)(hash % 55536); + port += 10000; + this.Address = new IPEndPoint(IPAddress.Loopback, port); } /// @@ -53,7 +50,7 @@ public void Resolve(string name, bool ip4Only) /// /// input /// hash value - private static int GetMurmurHash(string name) + private static uint GetMurmurHash(string name) { const uint seed = 0xc58f1a7b; const uint m = 0x5bd1e995; @@ -98,7 +95,7 @@ private static int GetMurmurHash(string name) hash ^= hash >> 13; hash *= m; hash ^= hash >> 15; - return (int)hash; + return hash; } [DisallowNull] From 180d3f3acc462b9da40cb4907279450cf54fdfb2 Mon Sep 17 00:00:00 2001 From: Bill Chung Date: Sun, 11 May 2025 01:37:11 +0800 Subject: [PATCH 3/3] unchecked --- src/NetMQ/Core/Transports/Ipc/IpcAddress.cs | 26 +++++++++++---------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs b/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs index c489ba703..e8e5e68b7 100644 --- a/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs +++ b/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs @@ -52,7 +52,7 @@ public void Resolve(string name, bool ip4Only) /// hash value private static uint GetMurmurHash(string name) { - const uint seed = 0xc58f1a7b; + const uint seed = 0xc58f1a7b; const uint m = 0x5bd1e995; const int r = 24; @@ -62,16 +62,16 @@ private static uint GetMurmurHash(string name) while (length >= 4) { - uint k = (uint)(name[currentIndex] | - (name[currentIndex + 1] << 8) | - (name[currentIndex + 2] << 16) | - (name[currentIndex + 3] << 24)); + uint k = unchecked((uint)(name[currentIndex] | + (name[currentIndex + 1] << 8) | + (name[currentIndex + 2] << 16) | + (name[currentIndex + 3] << 24))); - k *= m; + k = unchecked(k * m); k ^= k >> r; - k *= m; + k = unchecked(k * m); - hash *= m; + hash = unchecked(hash * m); hash ^= k; currentIndex += 4; @@ -81,23 +81,25 @@ private static uint GetMurmurHash(string name) switch (length) { case 3: - hash ^= (uint)(name[currentIndex + 2] << 16); + hash ^= unchecked((uint)(name[currentIndex + 2] << 16)); goto case 2; case 2: - hash ^= (uint)(name[currentIndex + 1] << 8); + hash ^= unchecked((uint)(name[currentIndex + 1] << 8)); goto case 1; case 1: hash ^= name[currentIndex]; - hash *= m; + hash = unchecked(hash * m); break; } hash ^= hash >> 13; - hash *= m; + hash = unchecked(hash * m); hash ^= hash >> 15; + return hash; } + [DisallowNull] public IPEndPoint? Address { get; private set; }