• David 'Digit' Turner's avatar
    Fix generation of empty output jars on Unix. · 654dd89d
    David 'Digit' Turner authored
    When the input is a tiny empty .jar file (e.g. 22 bytes that
    only include an empty End Of Central Directory record) as
    shown below, ijar generated an invalid output, which was
    supposed to only contain a single 'empty' file with length 0.
    
    The problem was due to the fact that MappedOutputFile did
    the following:
    
    - First call ftruncate(fd, 22) to size the output file from
      an estimate of the input file (blindly assuming the result
      would be smaller).
    
    - Later call ftruncate(fd, 108) to size the output with its
      'final' size. Unfortunately, the kernel interpreted that
      as _extending_ the file size, and overwriting the new
      bytes with zero.
    
    In practice, this means that the buffer's content before
    the second ftruncate() was:
    
    	00000000: 50 4b 03 04 0a 00 00 00 00 00 00 00 00 00 00 00
    	00000010: 00 00 00 00 00 00 00 00 00 00 05 00 00 00 64 75
    	00000020: 6d 6d 79 50 4b 01 02 00 00 0a 00 00 00 00 00 00
    	00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05
    	00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    	00000050: 00 64 75 6d 6d 79 50 4b 05 06 00 00 00 00 01 00
    	00000060: 01 00 33 00 00 00 23 00 00 00 00 00
    
    And after ftruncate() became:
    
    	00000000: 50 4b 03 04 0a 00 00 00 00 00 00 00 00 00 00 00
    	00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    	00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    	00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    	00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    	00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    	00000060: 00 00 00 00 00 00 00 00 00 00 00 00
    
    The result only contains a Local File Header record, but has no
    longer a final End Of Central Directory record, and is thus no
    longer a valid zip archive!
    
    This is fixed by this CL by ensuring that the initial ftruncate()
    is at least one page long. A sanity check is also added to return
    an error if the output file is larger than its input for some
    unexpected reason.
    
    This is not needed on Windows, which closes the file then
    later changes its size.
    
    -- example tiny input zip file of 22
    00000000: 504b 0506 0000 0000 0000 0000 0000 0000  PK..............
    00000010: 0000 0000 0000
    
    BUG=925257
    R=agrieve@chromium.org,dpranke@chromium.org,benmason@chromium.org
    
    Change-Id: If06b3ca88fee2dceaebacb427741ef48311cb38d
    Reviewed-on: https://chromium-review.googlesource.com/c/1436361Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
    Commit-Queue: Andrew Grieve <agrieve@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#626100}
    654dd89d
README.chromium 511 Bytes