CRC32 function produces incorrect values by default #18

Closed
opened 2022-01-01 22:00:50 +00:00 by alexgorbatchev · 2 comments
alexgorbatchev commented 2022-01-01 22:00:50 +00:00 (Migrated from github.com)

It appears that this library isn't producing expected results out of the box:

const crc32 = require("crc-32")
console.log(crc32.str('SheetJS').toString(16));
>
"-622fc6de"

However:

const crc32 = require("crc-32")
console.log((crc32.str('SheetJS') >>> 0).toString(16));
>
"9dd03922"

Same thing in Ruby:

require 'zlib'
puts(Zlib::crc32('SheetJS').to_s(16))
>
9dd03922

Same thing in Rust:

fn main() {
    let checksum = crc32fast::hash(b"SheetJS");
    println!("{:x}", checksum);
}
>
9dd03922
It appears that this library isn't producing expected results out of the box: ```js const crc32 = require("crc-32") console.log(crc32.str('SheetJS').toString(16)); > "-622fc6de" ``` However: ```js const crc32 = require("crc-32") console.log((crc32.str('SheetJS') >>> 0).toString(16)); > "9dd03922" ``` Same thing in Ruby: ```rb require 'zlib' puts(Zlib::crc32('SheetJS').to_s(16)) > 9dd03922 ``` Same thing in Rust: ```rs fn main() { let checksum = crc32fast::hash(b"SheetJS"); println!("{:x}", checksum); } > 9dd03922 ```
SheetJSDev commented 2022-01-01 23:26:41 +00:00 (Migrated from github.com)

A longer response was given in other issues, but to summarize:

  1. They are actually equivalent values, and you can confirm by using >>> 0 to convert to uint32_t and |0 to convert to int32_t:
> CRC32.str("SheetJS")
-1647298270
> CRC32.str("SheetJS") >>> 0
2647669026
> (CRC32.str("SheetJS") >>> 0).toString(16)
'9dd03922'

> 0x9dd03922 | 0
-1647298270
  1. The README notes the convention: https://github.com/SheetJS/js-crc32#usage

The return value is a signed 32-bit integer.

  1. The zlib conventions vary by platform. Python 2.x actually uses the signed values:
$ python --version
Python 2.7.18
$ python -c 'from zlib import crc32; print crc32("SheetJS")' 
-1647298270
  1. Back when we first released the library, V8 "small integer" (Smi) on 64-bit platforms corresponds to 32-bit signed integer (-2**31 to 2**31 - 1). Dealing with 32-bit unsigned integers outside of the range (2**31 to 2**32 - 1) triggered a deoptimization.
A longer response was given in [other issues](https://github.com/SheetJS/js-crc32/issues/4#issuecomment-170050796), but to summarize: 1) They are actually equivalent values, and you can confirm by using `>>> 0` to convert to uint32_t and `|0` to convert to int32_t: ```js > CRC32.str("SheetJS") -1647298270 > CRC32.str("SheetJS") >>> 0 2647669026 > (CRC32.str("SheetJS") >>> 0).toString(16) '9dd03922' > 0x9dd03922 | 0 -1647298270 ``` 2) The README notes the convention: https://github.com/SheetJS/js-crc32#usage > The return value is a signed 32-bit integer. 3) The zlib conventions vary by platform. Python 2.x actually uses the signed values: ``` $ python --version Python 2.7.18 $ python -c 'from zlib import crc32; print crc32("SheetJS")' -1647298270 ``` 4) Back when we first released the library, V8 "small integer" (Smi) on 64-bit platforms corresponds to 32-bit signed integer (`-2**31` to `2**31 - 1`). Dealing with 32-bit unsigned integers outside of the range (`2**31` to `2**32 - 1`) triggered a deoptimization.
alexgorbatchev commented 2022-01-01 23:48:06 +00:00 (Migrated from github.com)

Thanks for the follow up, I did read the README more carefully, but unfortunately only after posting the issue. Thank you for the detailed explanation!

Thanks for the follow up, I did read the README more carefully, but unfortunately only after posting the issue. Thank you for the detailed explanation!
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: sheetjs/js-crc32#18
No description provided.