mw99/DataCompression

DataCompression module generates a different adler32 checksum

TomBowden2019 opened this issue · 2 comments

Marcus,

I hate getting issues where someone says "there is a problem in your code..."
without giving details... so I hope you'll forgive my verbosity.

In C++, the following will generate a checksum of 0xA490238:

std::string test_string = "TEST CRC";
unsigned int a32 =  adler32(0L, (Bytef *)test_string.data(), test_string.length());

With the DataCompression module the same string generates a checksum of 0xA490239:

let test_crc = "TEST CRC"
var a32 = Adler32()
a32.advance(withChunk: test_crc.data(using:.utf8)!)
print ( "a32 = \(a32)" )

The issue appears to be related to the initialization of checksum for adler32:

--- DataCompression.swift:384 ---

/// Raw checksum. Updated after a every call to `advance(withChunk:)`
public var checksum:UInt32 = 1

--- DataCompression.swift:384 ---

In zlib/adler32, a 1L is returned only if the chunk being evaluated is null.
Otherwise, checksum starts with 0.

--- zlib-1.2.11/adler32.c:87 ---

 if (buf == Z_NULL)
        return 1L;

--- zlib-1.2.11/adler32.c:87 ---

Suggested fix:
initialize checksum to 0 (DataCompression.swift:385) and then,when returning checksum, return 1 if checksum == 0

--- DataCompression.swift:402 ---

    /// Formatted checksum.
    public var description: String
    {
        if checksum == 0 { // THB
            return "1"     // THB
        }                  // THB
        return String(format: "%08x", checksum)
    }

--- DataCompression.swift:402 ---

You would still have to account for checksum being read in other ways...

Thanks!

Tom Bowden
email: tommyBowden2014@gmail.com

mw99 commented

I hate getting issues where someone says "there is a problem in your code..."
without giving details... so I hope you'll forgive my verbosity.

Hi. No problem. I take on every issue :) Unfortunately, I believe there is problem in YOUR code 😄

If you use zlib in C or C++, instead of 0L you need the initial adler32 value. So I suggest you try adler32(0L, Z_NULL, 0); to get the initial value like:

  uLong adler = adler32(0L, Z_NULL, 0);

     while (read_buffer(buffer, length) != EOF) {
       adler = adler32(adler, buffer, length);
     }
     if (adler != original_adler) error();

(Please close this issue if it solves your problem.)

Such a mixed blessing to be proven wrong. Now I have to go back through all of my code where I missed that.

Thanks for the illumination!

Tom