change json parser to be more strict about whitespace (matching the spec)

This commit is contained in:
Robby Findler 2021-04-15 09:00:06 -05:00
parent fea6a0b9ae
commit 7cae0adaa6
3 changed files with 31 additions and 3 deletions

View File

@ -162,6 +162,9 @@ the @rfc for more information about JSON.
"false42" (code:comment "invalid JSON text sequence")
(λ () (read-json))))
]
@history[#:changed "8.1.0.2" @list{Adjusted the whitespace handling to reject whitespace that isn't either
@racket[#\space], @racket[#\tab], @racket[#\newline], or @racket[#\return].}]
}
@defproc[(string->jsexpr [str string?] [#:null jsnull any/c (json-null)])

View File

@ -151,6 +151,20 @@
;; Invalid UTF-8 input.
(bytes->jsexpr #"\"\377\377\377\"") =error> exn:fail?
;; whitespace should be only the four allowed charactes
(string->jsexpr (string-append
"{ \"x\" :"
(string #\u00A0)
" 123 }"))
=error>
#rx"whitespace that is not allowed"
(string->jsexpr (string-append
"[ 1,"
(string #\u00A0)
" 2 ]"))
=error>
#rx"whitespace that is not allowed"
;; More string escapes:
(string->jsexpr @T{ "hel\"lo" }) => "hel\"lo"
(string->jsexpr @T{ "\\//\\\\//" }) => "\\//\\\\//"

View File

@ -174,12 +174,23 @@
(define-values [l c p] (port-next-location i))
(raise-read-error (format "~a: ~a" who (apply format fmt args))
(object-name i) l c p #f))
(define (json-whitespace? ch)
(or (eq? ch #\space)
(eq? ch #\tab)
(eq? ch #\newline)
(eq? ch #\return)))
(define (skip-whitespace)
(define ch (peek-char i))
(cond
[(and (char? ch) (char-whitespace? ch))
(read-char i)
(skip-whitespace)]
[(char? ch)
(cond
[(json-whitespace? ch)
(read-char i)
(skip-whitespace)]
[(char-whitespace? ch)
(err "found whitespace that is not allowed by the json spec\n char: ~s"
ch)]
[else ch])]
[else ch]))
(define (byte-char=? b ch)
(eqv? b (char->integer ch)))