Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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]
  46.