Search code examples
delphidelphi-xe2fnv

FNV hash produces different result in 64 bit OS


I use FNV to hash a file in my 32 bit OS. Why the hash result of same code is different if I use the code in 64 bit OS?

Here's my code:

function gethash(const dwOffset: PByteArray; const dwLen: DWORD;
  const offset_basis: DWORD): DWORD;
var
  i: integer;
begin
  Result := offset_basis;
  try
    {$R-}{$I-}
    for i := 0 to dwLen - 1 do
      Result := (Result * 16777619) xor DWORD(dwOffset^[i]);
    {$R+}{$I+}
  except
    ;
  end;
end;

Solution

  • This code will produce the same output irrespective of the bitness of the operating system. Furthermore the output is independent of the bitness of the process. That is, if you compile for 32 bit and 64 bit, the output will be the same.

    The logical conclusion therefore, is that the different output is caused by supplying different input.

    One might ask why you have a swallow all exception handler in your code. That must be a really bad idea. If you supply incorrect parameters which lead to an access violation, you'll never find out. I urge you to remove that exception handler.


    To demonstrate my point, I offer the following simple test program:

    {$APPTYPE CONSOLE}
    
    uses
      Winapi.Windows,
      System.SysUtils;
    
    {$R-}{$I-}
    function gethash(const dwOffset: PByteArray; const dwLen: DWORD;
      const offset_basis: DWORD): DWORD;
    var
      i: integer;
    begin
      Result := offset_basis;
      for i := 0 to dwLen - 1 do
        Result := (Result * 16777619) xor DWORD(dwOffset^[i]);
    end;
    
    procedure Main;
    var
      i: Integer;
      buf: TBytes;
    begin
      SetLength(buf, 666);
      for i := 0 to high(buf) do
        buf[i] := (i+13)*7 mod 256;
      Writeln(gethash(PByteArray(buf), Length(buf), 17));
    end;
    
    begin
      Main;
      Readln;
    end.
    

    This produces the same output on every operating system, and the same output when compiled by either the 32 bit or 64 bit compiler. Whilst this does not prove that will be the case for every possible input, it gives you a test bed. You can replace my input with your own and you will discover, if I am right, that the output will always be the same, for fixed input.


    One plausible explanation for your problem is that you are reading beyond the end of the buffer and so hashing ill-defined input data. And perhaps with a different OS or compiler, that ill-defined input data differs.