Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6725 | siemargl | 1 | [Regarding an optimization to the bounds-checking code in the core |
2 | NEXTBYTE macro, which code is absolutely vital to the proper processing |
||
3 | of corrupt zipfiles (lack of checking can result in an infinite loop) |
||
4 | but which also slows processing.] |
||
5 | |||
6 | |||
7 | The key to the solution is a pair of small functions called |
||
8 | defer_leftover_input() and undefer_input(). The idea is, whenever |
||
9 | you are going to be processing input using NEXTBYTE, you call |
||
10 | defer_leftover_input(), and whenever you are going to process input by |
||
11 | any other means, such as readbuf(), ZLSEEK, or directly reading stuff |
||
12 | into G.inbuf, you call undefer_input(). What defer_leftover_input() |
||
13 | does is adjust G.incnt so that any data beyond the current end of file |
||
14 | is not visible. undefer_input() restores it to visibility. So when |
||
15 | you're calling NEXTBYTE (or NEEDBITS or READBITS), an end-of-data |
||
16 | condition only occurs at the same time as an end-of-buffer condition, |
||
17 | and can be handled inside readbyte() instead of needing a check in the |
||
18 | NEXTBYTE macro. Note: none of this applies to fUnZip. |
||
19 | |||
20 | In order for this to work, certain conditions have to be met: |
||
21 | |||
22 | 1) NEXTBYTE input must not be mixed with other forms of input involving |
||
23 | G.inptr and G.incnt. They must be separated by defer/undefer. |
||
24 | |||
25 | I believe this condition is fully met by simply bracketing the central |
||
26 | part of extract_or_test_member with defer/undefer, around the part |
||
27 | where the actual decompression is done, and another defer/undefer pair |
||
28 | in decrypt() around the reading of the RAND_HEADER_LEN password bytes. |
||
29 | |||
30 | When USE_ZLIB is defined, I think that calls of fillinbuf() must be |
||
31 | bracketed by defer/undefer. |
||
32 | |||
33 | 2) G.csize must not be assumed to contain the number of bytes left to |
||
34 | process, when decompressing with NEXTBYTE. Instead, it contains |
||
35 | the number of bytes left after the current buffer is exausted. To |
||
36 | check the number of bytes remaining, use (G.csize + G.incnt). |
||
37 | |||
38 | I believe the only places this change was needed were in explode.c, |
||
39 | mostly in the check at the end of each explode function that tests |
||
40 | whether the correct number of bytes has been read. G.incnt will |
||
41 | normally be zero at that time anyway. The other place is the line |
||
42 | that says "bd = G.csize > 200000L ? 8 : 7;" but that's just a rough |
||
43 | heuristic anyway. |
||
44 | |||
45 | [Paul Kienitz] |