racket/port: fix read-bytes-evt' and read-string-evt'

As the documentation says, it's supposed to be ok to use the
same evt multiple times or in multiple threads, but an internal
buffer was allocated incorrectly, so that multiple/concurrent
uses could go wrong.

Closes PR 12860

original commit: d253b89ba87b4bb295fd652708642046f4b90676
This commit is contained in:
Matthew Flatt 2012-06-22 06:56:49 +08:00
parent bd352c8455
commit 2ec1929ff3

View File

@ -1032,13 +1032,15 @@
(-read-bytes!-evt bstr input-port peek-offset prog-evt)) (-read-bytes!-evt bstr input-port peek-offset prog-evt))
(define (-read-bytes-evt len input-port peek-offset prog-evt) (define (-read-bytes-evt len input-port peek-offset prog-evt)
(let ([bstr (make-bytes len)]) (guard-evt
(wrap-evt (lambda ()
(-read-bytes!-evt bstr input-port peek-offset prog-evt) (let ([bstr (make-bytes len)])
(lambda (v) (wrap-evt
(if (number? v) (-read-bytes!-evt bstr input-port peek-offset prog-evt)
(if (= v len) bstr (subbytes bstr 0 v)) (lambda (v)
v))))) (if (number? v)
(if (= v len) bstr (subbytes bstr 0 v))
v)))))))
(define (read-bytes-evt len input-port) (define (read-bytes-evt len input-port)
(-read-bytes-evt len input-port #f #f)) (-read-bytes-evt len input-port #f #f))
@ -1049,44 +1051,46 @@
(define (-read-string-evt goal input-port peek-offset prog-evt) (define (-read-string-evt goal input-port peek-offset prog-evt)
(if (zero? goal) (if (zero? goal)
(wrap-evt always-evt (lambda (x) "")) (wrap-evt always-evt (lambda (x) ""))
(let ([bstr (make-bytes goal)] (guard-evt
[c (bytes-open-converter "UTF-8-permissive" "UTF-8")]) (lambda ()
(wrap-evt (let ([bstr (make-bytes goal)]
(read-at-least-bytes!-evt [c (bytes-open-converter "UTF-8-permissive" "UTF-8")])
bstr input-port (wrap-evt
(lambda (bstr v) (read-at-least-bytes!-evt
(if (= v (bytes-length bstr)) bstr input-port
;; We can't easily use bytes-utf-8-length here, (lambda (bstr v)
;; because we may need more bytes to figure out (if (= v (bytes-length bstr))
;; the true role of the last byte. The ;; We can't easily use bytes-utf-8-length here,
;; `bytes-convert' function lets us deal with ;; because we may need more bytes to figure out
;; the last byte properly. ;; the true role of the last byte. The
(let-values ([(bstr2 used status) ;; `bytes-convert' function lets us deal with
(bytes-convert c bstr 0 v)]) ;; the last byte properly.
(let ([got (bytes-utf-8-length bstr2)]) (let-values ([(bstr2 used status)
(if (= got goal) (bytes-convert c bstr 0 v)])
;; Done: (let ([got (bytes-utf-8-length bstr2)])
#f (if (= got goal)
;; Need more bytes: ;; Done:
(let ([bstr2 (make-bytes (+ v (- goal got)))]) #f
(bytes-copy! bstr2 0 bstr) ;; Need more bytes:
bstr2)))) (let ([bstr2 (make-bytes (+ v (- goal got)))])
;; Need more bytes in bstr: (bytes-copy! bstr2 0 bstr)
bstr)) bstr2))))
(lambda (bstr v) ;; Need more bytes in bstr:
;; We may need one less than v, bstr))
;; because we may have had to peek (lambda (bstr v)
;; an extra byte to discover an ;; We may need one less than v,
;; error in the stream. ;; because we may have had to peek
(if ((bytes-utf-8-length bstr #\? 0 v) . > . goal) (sub1 v) v)) ;; an extra byte to discover an
cons ;; error in the stream.
peek-offset prog-evt) (if ((bytes-utf-8-length bstr #\? 0 v) . > . goal) (sub1 v) v))
(lambda (bstr+v) cons
(let ([bstr (car bstr+v)] peek-offset prog-evt)
[v (cdr bstr+v)]) (lambda (bstr+v)
(if (number? v) (let ([bstr (car bstr+v)]
(bytes->string/utf-8 bstr #\? 0 v) [v (cdr bstr+v)])
v))))))) (if (number? v)
(bytes->string/utf-8 bstr #\? 0 v)
v)))))))))
(define (read-string-evt goal input-port) (define (read-string-evt goal input-port)
(-read-string-evt goal input-port #f #f)) (-read-string-evt goal input-port #f #f))