camlzip icon indicating copy to clipboard operation
camlzip copied to clipboard

Fix unchecked offsets during entry read

Open Ant1-Provot opened this issue 6 months ago • 3 comments

Description

Hi, working on camlzip I identified a bug that makes the read_entry function goes into an infinite loop for entries that have a negative offset or an offset bigger than the size of the file.

In that very specific case, the recursive function uncompr_finish L116 goes infinite as inflate always returns finished = false ; _ leading to an infinite loop.

It is hard to discuss the likeliness of this bug, as it's very unlikely to happen naturally in the wild, but is however very easy to craft with a very limited knowledge of the pkzip file format or application fuzzing.

For the record, zip obviously doesn't appreciate such crafted files, but doesn't go infinite :

🦆 ~/workspace $ unzip demo.zip                                                                            
Archive:  demo.zip
warning:  filename too long--truncating.
[ non-empty.txtUT^I ]
non-empty.txtUT^I:  bad extra field length (local)

Reproduction step

I created a little file that reproduces the bug minimally.

It contains a single entry of a non empty file, containing some text. Then, I tweaked both Filename Length (0x001A) and Extra Length (0x001C) with the maximal values (0xffff).

🦆 ~/workspace$ zipdetails demo.zip                                                                     

0000 LOCAL HEADER #1       04034B50
0004 Extract Zip Spec      14 '2.0'
0005 Extract OS            00 'MS-DOS'
0006 General Purpose Flag  0000
     [Bits 1-2]            0 'Normal Compression'
0008 Compression Method    0008 'Deflated'
000A Last Mod Time         59146C49 'Tue Aug 20 13:34:18 2024'
000E CRC                   8E94FE83
0012 Compressed Length     00000110
0016 Uncompressed Length   000001C3
001A Filename Length       FFFF
001C Extra Length          FFFF
Truncated file (got 418, wanted 65535):

You can find attached this file here : demo.zip

Type of change

This PR is a bug fix.

The implementation was straightforward, added a specific check in goto_entry raising an error in the case it happens.

Style of change

I tried to stick as much as possible to the coding style, but I have to admit I didn't find the coding convention of the repo, nor any formatting enforcement tool, so if I did wrong please tell me ! 😄

How Has This Been Tested?

  • [x] Ensured the issue happened on the attached file before my fix
  • [x] Ensured the issue did not happen on the attached file after my fix.

If you believe adding a test over that would make sense I'll also do it with pleasure. I believe having the attached file as part of the codebase would be a good call, but I'd like your opinion first and the way you believe it would be best to implement it.

Additional conversation

I noticed that the current codebase has limited test coverage, particularly around corner cases and unit tests. Having more tests could help ensure the reliability and maintainability of the code, especially as camlzip is a central element of the ocaml ecosystem.

If you're interested, I'd be happy to help write some tests or collaborate on improving the test coverage. Let me know how I can assist! 🥳

Ant1-Provot avatar Aug 20 '24 11:08 Ant1-Provot