untgz and gunzip: report unexpected end-of-file

Report an explicit "unexpected end-of-file" error instead of
a later contract failure on #<eof> insteda of a byte

Closes #1204
This commit is contained in:
Matthew Flatt 2016-04-17 15:51:24 -06:00
parent 734d81fed1
commit 027dd9a43c
2 changed files with 27 additions and 19 deletions

View File

@ -54,7 +54,7 @@
used if the block codes up smaller that way (usually for quite small used if the block codes up smaller that way (usually for quite small
chunks), otherwise the dynamic method is used. In the latter case, the chunks), otherwise the dynamic method is used. In the latter case, the
codes are customized to the probabilities in the current block, and so codes are customized to the probabilities in the current block, and so
can code it much better than the pre-determined fixed codes. < can code it much better than the pre-determined fixed codes.
The Huffman codes themselves are decoded using a mutli-level table The Huffman codes themselves are decoded using a mutli-level table
lookup, in order to maximize the speed of decoding plus the speed of lookup, in order to maximize the speed of decoding plus the speed of
@ -208,6 +208,12 @@
(define-const BMAX 16) ; /* maximum bit length of any code (16 for explode) */ (define-const BMAX 16) ; /* maximum bit length of any code (16 for explode) */
(define-const N_MAX 288) ; /* maximum number of codes in any set */ (define-const N_MAX 288) ; /* maximum number of codes in any set */
(define (read-byte/not-eof in)
(define b (read-byte in))
(when (eof-object? b)
(error 'inflate "unexpected end-of-file\n stream: ~e" in))
b)
(define (inflate input-port output-port) (define (inflate input-port output-port)
(define slide (make-bytes WSIZE)) (define slide (make-bytes WSIZE))
@ -864,14 +870,14 @@
(arithmetic-shift d 24))])) (arithmetic-shift d 24))]))
(define (do-gunzip in out name-filter) (define (do-gunzip in out name-filter)
(let ([header1 (read-byte in)] (let ([header1 (read-byte/not-eof in)]
[header2 (read-byte in)]) [header2 (read-byte/not-eof in)])
(unless (and (= header1 #o037) (= header2 #o213)) (unless (and (= header1 #o037) (= header2 #o213))
(error 'gnu-unzip "bad header"))) (error 'gnu-unzip "bad header")))
(let ([compression-type (read-byte in)]) (let ([compression-type (read-byte/not-eof in)])
(unless (= compression-type #o010) (unless (= compression-type #o010)
(error 'gnu-unzip "unknown compression type"))) (error 'gnu-unzip "unknown compression type")))
(let* ([flags (read-byte in)] (let* ([flags (read-byte/not-eof in)]
[ascii? (positive? (bitwise-and flags #b1))] [ascii? (positive? (bitwise-and flags #b1))]
[continuation? (positive? (bitwise-and flags #b10))] [continuation? (positive? (bitwise-and flags #b10))]
[has-extra-field? (positive? (bitwise-and flags #b100))] [has-extra-field? (positive? (bitwise-and flags #b100))]
@ -882,23 +888,23 @@
(error 'gnu-unzip "cannot unzip encrypted file")) (error 'gnu-unzip "cannot unzip encrypted file"))
(when continuation? (when continuation?
(error 'gnu-unzip "cannot handle multi-part files")) (error 'gnu-unzip "cannot handle multi-part files"))
(let ([unix-mod-time (make-small-endian (read-byte in) (read-byte in) (let ([unix-mod-time (make-small-endian (read-byte/not-eof in) (read-byte/not-eof in)
(read-byte in) (read-byte in))] (read-byte/not-eof in) (read-byte/not-eof in))]
[extra-flags (read-byte in)] [extra-flags (read-byte/not-eof in)]
[source-os (read-byte in)]) [source-os (read-byte/not-eof in)])
(when continuation? (when continuation?
(let ([part-number (make-small-endian (read-byte in) (read-byte in))]) (let ([part-number (make-small-endian (read-byte/not-eof in) (read-byte/not-eof in))])
'ok)) 'ok))
(when has-extra-field? (when has-extra-field?
(let ([len (make-small-endian (read-byte in) (read-byte in))]) (let ([len (make-small-endian (read-byte/not-eof in) (read-byte/not-eof in))])
(let loop ([len len]) (let loop ([len len])
(unless (zero? len) (unless (zero? len)
(read-byte in) (read-byte/not-eof in)
(loop (sub1 len)))))) (loop (sub1 len))))))
(let* ([read-null-term-string (let* ([read-null-term-string
(lambda () (lambda ()
(let loop ([s null]) (let loop ([s null])
(let ([r (read-byte in)]) (let ([r (read-byte/not-eof in)])
(if (zero? r) (if (zero? r)
(list->bytes (reverse s)) (list->bytes (reverse s))
(loop (cons r s))))))] (loop (cons r s))))))]
@ -908,7 +914,7 @@
(when encrypted? (when encrypted?
(let loop ([n 12]) (let loop ([n 12])
(unless (zero? n) (unless (zero? n)
(read-byte in) (read-byte/not-eof in)
(loop (sub1 n))))) (loop (sub1 n)))))
(let-values ([(out close?) (if out (let-values ([(out close?) (if out

View File

@ -30,8 +30,8 @@
(lambda (in) (lambda (in)
(define-values (in2 wait) (define-values (in2 wait)
(cond (cond
[(and (= (peek-byte in 0) #o037) [(and (= (peek-byte/not-eof in 0) #o037)
(= (peek-byte in 1) #o213)) (= (peek-byte/not-eof in 1) #o213))
(define-values (in2 out) (make-pipe 4096)) (define-values (in2 out) (make-pipe 4096))
(define t (define t
(thread (thread
@ -49,6 +49,8 @@
(untar in2 #:dest dest #:strip-count strip-count #:permissive? permissive? #:filter filter) (untar in2 #:dest dest #:strip-count strip-count #:permissive? permissive? #:filter filter)
(wait))))) (wait)))))
(define (peek-byte/not-eof in at)
(define b (peek-byte in at))
(when (eof-object? b)
(error 'untgz "unexpected end-of-file\n stream: ~e" in))
b)