From 14e53f9a75fb2d1d7ba69ea88a4b4f2220a9aa8c Mon Sep 17 00:00:00 2001 From: shove Date: Sun, 12 Nov 2023 17:30:05 +0800 Subject: [PATCH] compress.gzip: change the endianness for validation to conform to the gzip file specification (fix #19839) (#19849) --- vlib/compress/gzip/gzip.v | 16 +++---- vlib/compress/gzip/gzip_test.v | 2 +- vlib/compress/gzip/read_gz_files_test.v | 41 ++++++++++++++++++ vlib/compress/gzip/samples/known.gz | Bin 0 -> 213 bytes vlib/compress/gzip/samples/pwgen_13_20_1.gz | Bin 0 -> 232 bytes vlib/compress/gzip/samples/pwgen_13_20_2.gz | Bin 0 -> 228 bytes vlib/compress/gzip/samples/pwgen_13_20_3.gz | Bin 0 -> 227 bytes vlib/compress/gzip/samples/rand1.gz | Bin 0 -> 29 bytes vlib/compress/gzip/samples/rand2.gz | Bin 0 -> 29 bytes vlib/compress/gzip/samples/rand3.gz | Bin 0 -> 29 bytes vlib/compress/gzip/samples/readme_level_1.gz | Bin 0 -> 6225 bytes vlib/compress/gzip/samples/readme_level_5.gz | Bin 0 -> 5780 bytes vlib/compress/gzip/samples/readme_level_9.gz | Bin 0 -> 5761 bytes .../gzip/samples/readme_level_9_rsyncable.gz | Bin 0 -> 5812 bytes 14 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 vlib/compress/gzip/read_gz_files_test.v create mode 100644 vlib/compress/gzip/samples/known.gz create mode 100644 vlib/compress/gzip/samples/pwgen_13_20_1.gz create mode 100644 vlib/compress/gzip/samples/pwgen_13_20_2.gz create mode 100644 vlib/compress/gzip/samples/pwgen_13_20_3.gz create mode 100644 vlib/compress/gzip/samples/rand1.gz create mode 100644 vlib/compress/gzip/samples/rand2.gz create mode 100644 vlib/compress/gzip/samples/rand3.gz create mode 100644 vlib/compress/gzip/samples/readme_level_1.gz create mode 100644 vlib/compress/gzip/samples/readme_level_5.gz create mode 100644 vlib/compress/gzip/samples/readme_level_9.gz create mode 100644 vlib/compress/gzip/samples/readme_level_9_rsyncable.gz diff --git a/vlib/compress/gzip/gzip.v b/vlib/compress/gzip/gzip.v index 988314eb4b..b26294e529 100644 --- a/vlib/compress/gzip/gzip.v +++ b/vlib/compress/gzip/gzip.v @@ -28,14 +28,14 @@ pub fn compress(data []u8) ![]u8 { checksum := crc32.sum(data) length := data.len result << [ - u8(checksum >> 24), - u8(checksum >> 16), - u8(checksum >> 8), u8(checksum), - u8(length >> 24), - u8(length >> 16), - u8(length >> 8), + u8(checksum >> 8), + u8(checksum >> 16), + u8(checksum >> 24), u8(length), + u8(length >> 8), + u8(length >> 16), + u8(length >> 24), ] // 8 bytes return result } @@ -140,12 +140,12 @@ pub fn decompress(data []u8, params DecompressParams) ![]u8 { header_length := gzip_header.length decompressed := compr.decompress(data[header_length..data.len - 8], 0)! - length_expected := (u32(data[data.len - 4]) << 24) | (u32(data[data.len - 3]) << 16) | (u32(data[data.len - 2]) << 8) | data[data.len - 1] + length_expected := (u32(data[data.len - 1]) << 24) | (u32(data[data.len - 2]) << 16) | (u32(data[data.len - 3]) << 8) | data[data.len - 4] if params.verify_length && decompressed.len != length_expected { return error('length verification failed, got ${decompressed.len}, expected ${length_expected}') } checksum := crc32.sum(decompressed) - checksum_expected := (u32(data[data.len - 8]) << 24) | (u32(data[data.len - 7]) << 16) | (u32(data[data.len - 6]) << 8) | data[data.len - 5] + checksum_expected := (u32(data[data.len - 5]) << 24) | (u32(data[data.len - 6]) << 16) | (u32(data[data.len - 7]) << 8) | data[data.len - 8] if params.verify_checksum && checksum != checksum_expected { return error('checksum verification failed') } diff --git a/vlib/compress/gzip/gzip_test.v b/vlib/compress/gzip/gzip_test.v index 87ed44aecb..f785fe0f5a 100644 --- a/vlib/compress/gzip/gzip_test.v +++ b/vlib/compress/gzip/gzip_test.v @@ -123,7 +123,7 @@ fn test_gzip_with_invalid_length() { uncompressed := 'Hello world!' mut compressed := compress(uncompressed.bytes())! compressed[compressed.len - 1] += 1 - assert_decompress_error(compressed, 'length verification failed, got 12, expected 13')! + assert_decompress_error(compressed, 'length verification failed, got 12, expected 16777228')! } fn test_gzip_with_invalid_flags() { diff --git a/vlib/compress/gzip/read_gz_files_test.v b/vlib/compress/gzip/read_gz_files_test.v new file mode 100644 index 0000000000..c2c9e5543c --- /dev/null +++ b/vlib/compress/gzip/read_gz_files_test.v @@ -0,0 +1,41 @@ +import os +import compress.gzip + +const samples_folder = os.join_path(os.dir(@FILE), 'samples') + +fn s(fname string) string { + return os.join_path(samples_folder, fname) +} + +fn read_and_decode_file(fpath string) !([]u8, string) { + compressed := os.read_bytes(fpath)! + decoded := gzip.decompress(compressed)! + content := decoded.bytestr() + return compressed, content +} + +fn test_reading_and_decoding_a_known_gziped_file() { + compressed, content := read_and_decode_file(s('known.gz'))! + assert compressed#[0..3] == [u8(31), 139, 8] + assert compressed#[-5..] == [u8(127), 115, 1, 0, 0] + assert content.contains('## Description:') + assert content.contains('## Examples:') + assert content.ends_with('```\n') +} + +fn test_decoding_all_samples_files() { + for gz_file in os.walk_ext(samples_folder, '.gz') { + _, content := read_and_decode_file(gz_file)! + assert content.len > 0, 'decoded content should not be empty: `${content}`' + } +} + +fn test_reading_gzip_files_compressed_with_different_options() { + _, content1 := read_and_decode_file(s('readme_level_1.gz'))! + _, content5 := read_and_decode_file(s('readme_level_5.gz'))! + _, content9 := read_and_decode_file(s('readme_level_9.gz'))! + _, content9_rsyncable := read_and_decode_file(s('readme_level_9_rsyncable.gz'))! + assert content9_rsyncable == content9 + assert content9 == content5 + assert content5 == content1 +} diff --git a/vlib/compress/gzip/samples/known.gz b/vlib/compress/gzip/samples/known.gz new file mode 100644 index 0000000000000000000000000000000000000000..98448f12ecc7a02f0a9aa65bd1f414fd906f8df9 GIT binary patch literal 213 zcmV;`04o0l$yYmn^AB3@4)D5`D_7+TEU#28hDIM>{%3`7{MaRkSE1OgCeZPi~lC z$?_J7SDYo7{D3vZU{nb=41dWR9TC+v-oK4cj&*J^40jTrVlLPfBDw~6BcW;WqG}8a z%NC~|#}9Tc;wxrn4@au@>>SW7P_y-R=SN{}+V()zx?tm4!DeM=_4E#&O72X3kN?8y PXWm7>)cJgWa{&MVHIZH& literal 0 HcmV?d00001 diff --git a/vlib/compress/gzip/samples/pwgen_13_20_1.gz b/vlib/compress/gzip/samples/pwgen_13_20_1.gz new file mode 100644 index 0000000000000000000000000000000000000000..0528f855010208ed326191e8adf236d7705627a1 GIT binary patch literal 232 zcmVVohT;8O4a)x#vD#{5H6H>DqE29%+Po=CiU zS-h(!uRw32ctX0dmiC5;^#_sXhzU;2rnT&_T5qLVu{DV|C`nPLW{X)e^OkPG0qM?X z11?G|i`_j~$w!l(fMqdQ8dDIM)4A?P8c5{r3#J{=p%~GgmmB;h=5nKj#%5gl35ay--xu4GJIvM iXXSzZSbdn~{+qQi+AH2%a%8y%75WFd!c0~e0RRA?@oAm_ literal 0 HcmV?d00001 diff --git a/vlib/compress/gzip/samples/pwgen_13_20_2.gz b/vlib/compress/gzip/samples/pwgen_13_20_2.gz new file mode 100644 index 0000000000000000000000000000000000000000..920ea5efbc57e3a6db742037f4829e3dc4731d9d GIT binary patch literal 228 zcmVAL}4gv2M=(YGCX*J{s7KaRS4t)b5)JF%p&WBhs%O^ERY#KLSv6zZW_<;19SmVoUI zIsxCAGNQTrktIVA$qs?Bm3PGDX%akBka5@MCB(sqA2+7Tlv~^I}qx`PpXZsp$q@=+1b1O2V_*=I^lwjrmEV e_@quxthMb-YE?4pO>z?{EK2`4l)Ek%0RRA`op9y= literal 0 HcmV?d00001 diff --git a/vlib/compress/gzip/samples/pwgen_13_20_3.gz b/vlib/compress/gzip/samples/pwgen_13_20_3.gz new file mode 100644 index 0000000000000000000000000000000000000000..9b04afec97d1e04a7a5f3a8f1080f48cc6100227 GIT binary patch literal 227 zcmV<90381xiwFP!000000~L?SPQySDMDP7I$au*dtq>uCAc$BX<<^G6)s9Ig@{GXw zdWLgtuV!UTJ{2v$y%*=6%IfHTCgg)a-CDGxB8cI9LNc}g7%XP+b&E;;|uD=tYkr@=6(ofX9>XaO{s0X9QiB))007EsY;OPn literal 0 HcmV?d00001 diff --git a/vlib/compress/gzip/samples/rand1.gz b/vlib/compress/gzip/samples/rand1.gz new file mode 100644 index 0000000000000000000000000000000000000000..fa405317f3e76737ef4b24cb1fb1f68ee57ee3f7 GIT binary patch literal 29 gcmb2|=3oE=W^KPSE4)e!y`C~LXm1qq;{=KV09SMd2mk;8 literal 0 HcmV?d00001 diff --git a/vlib/compress/gzip/samples/rand2.gz b/vlib/compress/gzip/samples/rand2.gz new file mode 100644 index 0000000000000000000000000000000000000000..ed784d350731dfa39eebed0cbd09056339ed5bc1 GIT binary patch literal 29 gcmb2|=3oE==Fi{HnXfu={=_3DhM5YrCY(S~0EE5?1poj5 literal 0 HcmV?d00001 diff --git a/vlib/compress/gzip/samples/rand3.gz b/vlib/compress/gzip/samples/rand3.gz new file mode 100644 index 0000000000000000000000000000000000000000..4d47d0d149f07e70565ecf472b1084951238810e GIT binary patch literal 29 gcmb2|=3oE=W^eB^AG}IVn>=A+FjC;y!3h)v0Aln8#sB~S literal 0 HcmV?d00001 diff --git a/vlib/compress/gzip/samples/readme_level_1.gz b/vlib/compress/gzip/samples/readme_level_1.gz new file mode 100644 index 0000000000000000000000000000000000000000..d5a92822ca1e40a3c53e10362dca6889054b794b GIT binary patch literal 6225 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 literal 0 HcmV?d00001 diff --git a/vlib/compress/gzip/samples/readme_level_9_rsyncable.gz b/vlib/compress/gzip/samples/readme_level_9_rsyncable.gz new file mode 100644 index 0000000000000000000000000000000000000000..447b3c21dbc0f9d2d4fec01b3c713a6013eb7fd2 GIT binary patch literal 5812 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