From 2ec1929ff3e3a57043dd1585c2c47d8971059b54 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 22 Jun 2012 06:56:49 +0800 Subject: [PATCH] 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 --- collects/mzlib/port.rkt | 94 +++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/collects/mzlib/port.rkt b/collects/mzlib/port.rkt index e373aaf..98dbebb 100644 --- a/collects/mzlib/port.rkt +++ b/collects/mzlib/port.rkt @@ -1032,13 +1032,15 @@ (-read-bytes!-evt bstr input-port peek-offset prog-evt)) (define (-read-bytes-evt len input-port peek-offset prog-evt) - (let ([bstr (make-bytes len)]) - (wrap-evt - (-read-bytes!-evt bstr input-port peek-offset prog-evt) - (lambda (v) - (if (number? v) - (if (= v len) bstr (subbytes bstr 0 v)) - v))))) + (guard-evt + (lambda () + (let ([bstr (make-bytes len)]) + (wrap-evt + (-read-bytes!-evt bstr input-port peek-offset prog-evt) + (lambda (v) + (if (number? v) + (if (= v len) bstr (subbytes bstr 0 v)) + v))))))) (define (read-bytes-evt len input-port) (-read-bytes-evt len input-port #f #f)) @@ -1049,44 +1051,46 @@ (define (-read-string-evt goal input-port peek-offset prog-evt) (if (zero? goal) (wrap-evt always-evt (lambda (x) "")) - (let ([bstr (make-bytes goal)] - [c (bytes-open-converter "UTF-8-permissive" "UTF-8")]) - (wrap-evt - (read-at-least-bytes!-evt - bstr input-port - (lambda (bstr v) - (if (= v (bytes-length bstr)) - ;; We can't easily use bytes-utf-8-length here, - ;; because we may need more bytes to figure out - ;; the true role of the last byte. The - ;; `bytes-convert' function lets us deal with - ;; the last byte properly. - (let-values ([(bstr2 used status) - (bytes-convert c bstr 0 v)]) - (let ([got (bytes-utf-8-length bstr2)]) - (if (= got goal) - ;; Done: - #f - ;; Need more bytes: - (let ([bstr2 (make-bytes (+ v (- goal got)))]) - (bytes-copy! bstr2 0 bstr) - bstr2)))) - ;; Need more bytes in bstr: - bstr)) - (lambda (bstr v) - ;; We may need one less than v, - ;; because we may have had to peek - ;; an extra byte to discover an - ;; error in the stream. - (if ((bytes-utf-8-length bstr #\? 0 v) . > . goal) (sub1 v) v)) - cons - peek-offset prog-evt) - (lambda (bstr+v) - (let ([bstr (car bstr+v)] - [v (cdr bstr+v)]) - (if (number? v) - (bytes->string/utf-8 bstr #\? 0 v) - v))))))) + (guard-evt + (lambda () + (let ([bstr (make-bytes goal)] + [c (bytes-open-converter "UTF-8-permissive" "UTF-8")]) + (wrap-evt + (read-at-least-bytes!-evt + bstr input-port + (lambda (bstr v) + (if (= v (bytes-length bstr)) + ;; We can't easily use bytes-utf-8-length here, + ;; because we may need more bytes to figure out + ;; the true role of the last byte. The + ;; `bytes-convert' function lets us deal with + ;; the last byte properly. + (let-values ([(bstr2 used status) + (bytes-convert c bstr 0 v)]) + (let ([got (bytes-utf-8-length bstr2)]) + (if (= got goal) + ;; Done: + #f + ;; Need more bytes: + (let ([bstr2 (make-bytes (+ v (- goal got)))]) + (bytes-copy! bstr2 0 bstr) + bstr2)))) + ;; Need more bytes in bstr: + bstr)) + (lambda (bstr v) + ;; We may need one less than v, + ;; because we may have had to peek + ;; an extra byte to discover an + ;; error in the stream. + (if ((bytes-utf-8-length bstr #\? 0 v) . > . goal) (sub1 v) v)) + cons + peek-offset prog-evt) + (lambda (bstr+v) + (let ([bstr (car bstr+v)] + [v (cdr bstr+v)]) + (if (number? v) + (bytes->string/utf-8 bstr #\? 0 v) + v))))))))) (define (read-string-evt goal input-port) (-read-string-evt goal input-port #f #f))