Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implement universal hashing for niecza hashes
It appears to be a few percent slower than the builtin string.GetHashCode,
but proof against hash-based algorithmic complexity attacks is hard to
replace...
  • Loading branch information
sorear committed Mar 30, 2012
1 parent b4b916a commit e08dd76
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 19 deletions.
2 changes: 1 addition & 1 deletion lib/CodeGen.cs
Expand Up @@ -3652,7 +3652,7 @@ public class DowncallReceiver : CallReceiver {
Kernel.TraceFlags = Kernel.TRACE_CUR;
Kernel.TraceCount = Kernel.TraceFreq = 1;
}
Kernel.SetTrace();
Kernel.InitGlobal();
Backend.obj_dir = (string)args[1];
Builtins.upcall_receiver = (System.Collections.IDictionary)args[2];
return null;
Expand Down
13 changes: 11 additions & 2 deletions lib/Kernel.cs
Expand Up @@ -4740,6 +4740,15 @@ public class Kernel {
[CompartmentGlobal] internal static SubInfo CommonGrep_I;
[CompartmentGlobal] internal static SubInfo TEMP_SI;

internal static void InitGlobal() {
Random r = new Random();
VarHash.string_hash_argument =
(uint)r.Next(VarHash.HASH_ARG_MAX + 1);
VarHash.hash_automorphism =
((uint)r.Next(int.MaxValue)) * 2 + 1;
SetTrace();
}

internal static void InitCompartment() {
RuntimeUnit.reg = new ObjectRegistry();

Expand Down Expand Up @@ -6518,7 +6527,7 @@ class LastFrameNode {

public static void MainHandler(string uname, string[] args) {
InitCompartment();
SetTrace();
InitGlobal();
commandArgs = args;

RuntimeUnit ru = (RuntimeUnit)
Expand Down Expand Up @@ -6555,7 +6564,7 @@ class LastFrameNode {
string cmd = args.Length > 0 ? args[0] : "-help";

InitCompartment();
SetTrace();
InitGlobal();

if (cmd == "-field-inventory") {
foreach (Type ty in typeof(Kernel).Assembly.GetTypes()) {
Expand Down
50 changes: 34 additions & 16 deletions lib/Utils.cs
Expand Up @@ -204,16 +204,35 @@ public sealed class VarHash : IEnumerable<KeyValuePair<string,Variable>>,
VarHashLink[] heap;
int[] htab;

const int INITIAL = 5;
const int THRESHOLD = 11;

[Immutable]
static int[] grow = new int[] {
5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 16411,
32771, 65537, 131101, 262147, 524309, 1048583, 2097169, 4194319,
8388617, 16777259, 33554467, 67108879, 134217757, 268435459,
536870923, 1073741827
};
const int INITIAL = 4;
const int THRESHOLD = 8;

// sacrifices a bit of universality to save a reduction step
public const int HASH_ARG_MAX = 1073709057;
[TrueGlobal]
public static uint string_hash_argument;
public static uint hash_automorphism;

public static unsafe int UniversalHash(int buckets, string str) {
fixed(char *c = str) {
char *cc = c;
char *end = cc + str.Length;
uint accum = 0;
while (cc < end) {
// accum <= 2^32-1-65535
accum += *(cc++);
// accum <= 2^32-1
ulong temp = (ulong)accum * string_hash_argument;
// temp <= (2^32-1) * HASH_ARG_MAX
// temp <= 4611545284160290815
accum = (uint)((temp & 0x7FFFFFFF) + (temp >> 31));
// accum <= floor(temp / 2^31) + (2^31-1)
// accum <= 4294901760 = 2^32-1-65535
}
ulong temp2 = (ulong)accum * (uint)buckets;
return (int) (temp2 >> 32);
}
}

public VarHash() { Clear(); }

Expand Down Expand Up @@ -255,8 +274,7 @@ public sealed class VarHash : IEnumerable<KeyValuePair<string,Variable>>,
return;
}

int bkt = (int)(((uint) key.GetHashCode()) %
((uint) htab.Length));
int bkt = UniversalHash(htab.Length, key);
int ptr = htab[bkt];

if (ptr < 0) {
Expand Down Expand Up @@ -307,11 +325,11 @@ public sealed class VarHash : IEnumerable<KeyValuePair<string,Variable>>,

void rehash(int ordel) {
int rank = 0;
while (heap.Length != grow[rank]) rank++;
while (heap.Length != (1 << (rank + 2))) rank++;
rank += ordel;

VarHashLink[] oheap = heap;
init(grow[rank]);
init(1 << (rank + 2));

foreach (VarHashLink vhl in oheap)
if (vhl.key != null)
Expand All @@ -338,7 +356,7 @@ public sealed class VarHash : IEnumerable<KeyValuePair<string,Variable>>,
return false;
}

int bkt = (int)(((uint) key.GetHashCode()) % ((uint) htab.Length));
int bkt = UniversalHash(htab.Length, key);
int ptr = htab[bkt];

if (ptr < 0)
Expand Down Expand Up @@ -419,7 +437,7 @@ public sealed class VarHash : IEnumerable<KeyValuePair<string,Variable>>,
return false;
}

int ptr = htab[((uint) key.GetHashCode()) % ((uint) htab.Length)];
int ptr = htab[UniversalHash(htab.Length, key)];

while (ptr >= 0) {
if (heap[ptr].key == key) {
Expand Down

0 comments on commit e08dd76

Please sign in to comment.