aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Tatham <anakin@pobox.com>2017-05-16 20:11:53 +0100
committerSimon Tatham <anakin@pobox.com>2017-05-16 20:11:53 +0100
commit4aa85aa621dd2fd0b33a74ceb6821213846df7da (patch)
treec14095d41b4eb977c4edab4fc5ba25ed5d2ed93d
parentdc057115b5068fe6edf209a706a43893a67f3469 (diff)
downloadwix-on-linux-4aa85aa621dd2fd0b33a74ceb6821213846df7da.tar.gz
wix-on-linux-4aa85aa621dd2fd0b33a74ceb6821213846df7da.tar.bz2
wix-on-linux-4aa85aa621dd2fd0b33a74ceb6821213846df7da.zip
Fix checksum calculation in CAB data records.
[MS-CAB] is pretty unclearly worded in this area. Turns out that if the sequence of bytes being checksummed is not a multiple of 4 bytes, you are supposed to _first_ reverse the order of the trailing (n % 4) bytes, and _then_ append zero bytes to pad to a multiple of 4, before you do the main checksum operation of XORing together all the 32-bit words of the input.
-rwxr-xr-xmakecab.py6
1 files changed, 5 insertions, 1 deletions
diff --git a/makecab.py b/makecab.py
index befa94a..77c1e4f 100755
--- a/makecab.py
+++ b/makecab.py
@@ -34,7 +34,11 @@ def packtime(h,m,s):
34 return ((h << 11) | (m << 5) | (s >> 1)) 34 return ((h << 11) | (m << 5) | (s >> 1))
35 35
36def checksum(data): 36def checksum(data):
37 data += "\0" * (3 & -len(data)) # pad to multiple of 4 bytes 37 data_full_words = data[:len(data) & ~3]
38 data_last_word = data[len(data_full_words):]
39 data_last_word = "".join(reversed(data_last_word))
40 data_last_word += "\0" * (3 & -len(data)) # pad to multiple of 4 bytes
41 data = data_full_words + data_last_word
38 toret = 0 42 toret = 0
39 for offset in xrange(0, len(data), 4): 43 for offset in xrange(0, len(data), 4):
40 toret ^= struct.unpack_from("<L", data, offset)[0] 44 toret ^= struct.unpack_from("<L", data, offset)[0]