Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent results from std::hash::crc32() #312

Open
phipolis opened this issue Oct 12, 2024 · 2 comments
Open

Inconsistent results from std::hash::crc32() #312

phipolis opened this issue Oct 12, 2024 · 2 comments

Comments

@phipolis
Copy link

phipolis commented Oct 12, 2024

I'm observing unexpected behavior in ImHex 1.35.4 where std::hash::crc32() returns a different result on every evaluation in the pattern editor console.

Context: I am writing a pattern to parse a 512-byte structure. The first 8 bytes describe a checksum and seed checking the 504 bytes that follow. (It's a CRC32-C variant - no xorout)
I can produce the expected result by selecting the 504 bytes in the 'Hashes' view (screenshot). However I'm unable to achieve the same result in the pattern editor. Instead I am seeing constantly shifting values.

image

The sketch below illustrates what I'm seeing. Am I misusing something or does it seem like an issue with std::hash::crc32()?

import std.hash;
import type.magic;
#define FVAULT2_VOL_HEADER_SIZE 512
#define CRC32C_POLYNOMIAL 0x1edc6f41

struct CRC32_CHECKSUM { 
    u32 value;
    u32 seed;
};

struct VOLUME_HEADER {
  CRC32_CHECKSUM crc32;
  std::print("CRC expected: {0:#x} / seed {1:#x}", crc32.value, crc32.seed);

  // ... [FIELDS OMITTED] ...

  // Jump back & capture all field bytes as a whole:
  $ = addressof(this) + sizeof(crc32);
  std::print("CRC32C: {} bytes @{}", FVAULT2_VOL_HEADER_SIZE - sizeof(crc32), $);
  u8 crcBytes[FVAULT2_VOL_HEADER_SIZE - sizeof(crc32)] [[hidden]];
  u32 crc_computed_1 = std::hash::crc32(crcBytes, crc32.seed, CRC32C_POLYNOMIAL, 0x0, true, true);
  std::print("Calculated1 {0:#x}", crc_computed_1);

  // Try again with explicit addresses 
  $ = 0x8;
  u8 crcBytes_2[504];
  u32 crc_computed_2 = std::hash::crc32(crcBytes_2, crc32.seed, CRC32C_POLYNOMIAL, 0x0, true, true);
  std::print("Calculated2 {0:#x}", crc_computed_2);
};
VOLUME_HEADER volume_header @ 0x00;

Evaluation:

I: CRC expected: 0x4d65756 / seed 0xffffffff
I: CRC32C: 504 bytes @8
I: Calculated1 0xea9dc936
I: Calculated2 0x4b652509
I: Pattern exited with code: 0
I: Evaluation took 0.0195119s

Next evaluation:

I: CRC expected: 0x4d65756 / seed 0xffffffff
I: CRC32C: 504 bytes @8
I: Calculated1 0xca7d6643
I: Calculated2 0x3be812d3
I: Pattern exited with code: 0
I: Evaluation took 0.0222181s
@paxcut
Copy link
Contributor

paxcut commented Oct 12, 2024

I tested using the standard crc32 and I also get results that change on every run and that obviously differ from any other crc32 implementation I tried. The only way I can get it to behave consistently and give the expected result is to use an array of chars instead of using u8 or s8.

I couldn't test your code because no input file is provided, but you can try and see if this is related to what you are seeing.
To test this in your code, instead of using

u8 crcBytes[FVAULT2_VOL_HEADER_SIZE - sizeof(crc32)] [[hidden]];

try using

char crcBytes[FVAULT2_VOL_HEADER_SIZE - sizeof(crc32)] [[hidden]];

and the same for the other tests.
Why does it need to use chars? I am not sure. Somebody who knows more about crc32 may know why this is happening. There is also the possibility of this being a bug but I can't imagine what the bug would be or how to fix it.

@phipolis
Copy link
Author

phipolis commented Oct 12, 2024

@paxcut As you say, it works as expected with type char instead of u8. Thank you for the suggestion!

Here is a 512B sample file with a CRC at the beginning that satisfies the pattern:
[ImHex-Patterns_Issue_312_Sample.zip](https://github.com/user-attachments/files/17351465/ImHex-
Patterns_Issue_312_Sample.zip)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants