images.tiff: Fix infinite loop bug exposed by AFL test suite. IDFs are found at certain offsets, then the next offset is after the IDF. If a next-offset is its own previous offset, then it would loop. Now we record the offset and stop if it would loop.

db4
Doug Coleman 2015-02-13 14:58:18 -08:00
parent 857e60db5b
commit 7f40cadf8b
1 changed files with 44 additions and 28 deletions

View File

@ -1,31 +1,31 @@
! Copyright (C) 2009 Doug Coleman. ! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays assocs byte-arrays classes combinators USING: accessors arrays assocs byte-arrays combinators
compression.lzw endian fry grouping images io combinators.short-circuit compression.lzw endian fry grouping
io.binary io.encodings.ascii io.encodings.binary images images.loader io io.binary io.encodings.ascii
io.encodings.string io.encodings.utf8 io.files kernel math io.encodings.string io.encodings.utf8 io.streams.throwing kernel
math.bitwise math.order math.parser pack sequences math math.bitwise math.vectors pack sequences ;
strings math.vectors specialized-arrays locals
images.loader io.streams.throwing ;
FROM: alien.c-types => float ;
SPECIALIZED-ARRAY: float
IN: images.tiff IN: images.tiff
SINGLETON: tiff-image SINGLETON: tiff-image
TUPLE: loading-tiff endianness the-answer ifd-offset ifds ; TUPLE: loading-tiff endianness the-answer ifd-offset ifd-offsets ifds ;
: <loading-tiff> ( -- tiff ) : <loading-tiff> ( -- tiff )
loading-tiff new V{ } clone >>ifds ; loading-tiff new
H{ } clone >>ifds ; inline
TUPLE: ifd count ifd-entries next ! offset, next-offset, and count are not strictly necessary here
processed-tags strips bitmap ; ! count is just the length of ifd-entries
TUPLE: ifd offset next-offset count
ifd-entries processed-tags strips bitmap ;
: <ifd> ( count ifd-entries next -- ifd ) : <ifd> ( offset count ifd-entries next-offset -- ifd )
ifd new ifd new
swap >>next swap >>next-offset
swap >>ifd-entries swap >>ifd-entries
swap >>count ; swap >>count
swap >>offset ;
TUPLE: ifd-entry tag type count offset/value ; TUPLE: ifd-entry tag type count offset/value ;
@ -242,20 +242,34 @@ ERROR: bad-tiff-magic bytes ;
4 read endian> >>ifd-offset 4 read endian> >>ifd-offset
] with-endianness ; ] with-endianness ;
: push-ifd ( tiff ifd -- tiff ) over ifds>> push ; : store-ifd ( tiff ifd -- tiff )
dup offset>> pick ifds>> set-at ;
: read-ifd ( -- ifd ) : read-ifd-entry ( -- ifd )
2 read endian> 2 read endian>
2 read endian> 2 read endian>
4 read endian> 4 read endian>
4 read endian> <ifd-entry> ; 4 read endian> <ifd-entry> ;
: read-ifds ( tiff offset -- tiff ) : read-ifd ( offset -- ifd )
seek-absolute seek-input dup seek-absolute seek-input
2 read endian> 2 read endian>
dup [ read-ifd ] replicate dup [ read-ifd-entry ] replicate
! next ifd offset, 0 for stop
4 read endian> 4 read endian>
[ <ifd> push-ifd ] [ dup 0 = [ drop ] [ read-ifds ] if ] bi ; <ifd> ;
: read-ifds ( tiff offset -- tiff )
read-ifd
[ store-ifd ]
[
next-offset>> dup { [ 0 > ] [ pick ifds>> key? not ] } 1&& [
read-ifds
] [
drop
] if
] bi ;
ERROR: no-tag class ; ERROR: no-tag class ;
@ -278,11 +292,13 @@ ERROR: no-tag class ;
[ seek-absolute seek-input read ] { } 2map-as [ seek-absolute seek-input read ] { } 2map-as
] if >>strips ; ] if >>strips ;
ERROR: unknown-ifd-type n ; ERROR: unknown-ifd-type n where ;
: bytes>bits ( n/byte-array -- n ) : bytes>bits ( n/byte-array -- n )
dup byte-array? [ le> ] when ; dup byte-array? [ le> ] when ;
! TODO: Should skip entire ifd-entry instead of throwing
! if type is unknown (e.g. type 0 from the AFL american fuzzy loop test cases)
: value-length ( ifd-entry -- n ) : value-length ( ifd-entry -- n )
[ count>> ] [ type>> ] bi { [ count>> ] [ type>> ] bi {
{ 1 [ ] } { 1 [ ] }
@ -298,7 +314,7 @@ ERROR: unknown-ifd-type n ;
{ 11 [ 4 * ] } { 11 [ 4 * ] }
{ 12 [ 8 * ] } { 12 [ 8 * ] }
{ 13 [ 4 * ] } { 13 [ 4 * ] }
[ unknown-ifd-type ] [ "value-length" unknown-ifd-type ]
} case ; } case ;
ERROR: bad-small-ifd-type n ; ERROR: bad-small-ifd-type n ;
@ -331,7 +347,7 @@ ERROR: bad-small-ifd-type n ;
{ 10 [ 8 group [ "ii" unpack first2 / ] map ] } { 10 [ 8 group [ "ii" unpack first2 / ] map ] }
{ 11 [ 4 group [ "f" unpack ] map ] } { 11 [ 4 group [ "f" unpack ] map ] }
{ 12 [ 8 group [ "d" unpack ] map ] } { 12 [ 8 group [ "d" unpack ] map ] }
[ unknown-ifd-type ] [ "offeset-bytes>obj" unknown-ifd-type ]
} case ; } case ;
: ifd-entry-value ( ifd-entry -- n ) : ifd-entry-value ( ifd-entry -- n )
@ -430,7 +446,7 @@ ERROR: bad-small-ifd-type n ;
[ [
dup ifd-entries>> dup ifd-entries>>
[ process-ifd-entry swap ] H{ } map>assoc >>processed-tags [ process-ifd-entry swap ] H{ } map>assoc >>processed-tags
] map ] assoc-map
] change-ifds ; ] change-ifds ;
ERROR: unhandled-compression compression ; ERROR: unhandled-compression compression ;
@ -514,7 +530,7 @@ ERROR: unknown-component-order ifd ;
} cleave ; } cleave ;
: tiff>image ( image -- image ) : tiff>image ( image -- image )
ifds>> [ ifd>image ] map first ; ifds>> values [ ifd>image ] map first ;
: with-tiff-endianness ( loading-tiff quot -- ) : with-tiff-endianness ( loading-tiff quot -- )
[ dup endianness>> ] dip with-endianness ; inline [ dup endianness>> ] dip with-endianness ; inline
@ -552,7 +568,7 @@ ERROR: unknown-component-order ifd ;
] if ; ] if ;
: process-tif-ifds ( loading-tiff -- ) : process-tif-ifds ( loading-tiff -- )
ifds>> [ process-ifd ] each ; ifds>> values [ process-ifd ] each ;
: load-tiff ( -- loading-tiff ) : load-tiff ( -- loading-tiff )
load-tiff-ifds dup load-tiff-ifds dup