Skip to content

Commit 45798a2

Browse files
committed
Fix read of number followed by EOF can break subsequent read from seeing EOF
1 parent dbff2f7 commit 45798a2

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ Change Log
151151
----------------------------------------
152152

153153
* next
154-
* In `read`, update docstring to specify minimum buffer size if PushbackReader supplied
154+
* Fix: `read` of number followed by EOF can break subsequent read from seeing EOF
155+
* In `read`, update docstring to specify minimum buffer size when PushbackReader supplied
155156
* Release [2.5.0] on 2023-Dec-21
156157
* Fix [DJSON-50]: `read` can take a PushbackReader for repeated read use case
157158
* Fix `write` docstring to add `:indent` option added in [DJSON-18]

src/main/clojure/clojure/data/json.clj

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
(readChars [_ buffer start bufflen]
3434
(.read rdr ^chars buffer start bufflen))
3535
(unreadChar [_ c]
36+
;; ASSERT: c should never be -1 (EOF)
3637
(.unread rdr c))
3738
(unreadChars [_ buffer start bufflen]
3839
(.unread rdr buffer start bufflen))
@@ -63,6 +64,7 @@
6364
(.getChars ^String s p end ^chars buffer start)))
6465
(if (pos? n) n -1)))
6566
(unreadChar [_ _c]
67+
;; ASSERT: c should never be -1 (EOF)
6668
(set! pos (unchecked-dec pos))
6769
nil)
6870
(unreadChars [_ _buffer _start bufflen]
@@ -234,9 +236,11 @@
234236
:whitespace
235237
(do (.unreadChar stream c)
236238
false)
237-
(\, \] \} -1)
239+
(\, \] \})
238240
(do (.unreadChar stream c)
239241
false)
242+
-1
243+
false
240244
(throw (Exception. "JSON error (invalid number literal)")))
241245
;; previous character is a "0"
242246
:frac-point
@@ -251,9 +255,11 @@
251255
:whitespace
252256
(do (.unreadChar stream c)
253257
false)
254-
(\, \] \} -1)
258+
(\, \] \})
255259
(do (.unreadChar stream c)
256260
false)
261+
-1
262+
false
257263
;; Disallow zero-padded numbers or invalid characters
258264
(throw (Exception. "JSON error (invalid number literal)")))
259265
;; previous character is a "."
@@ -276,9 +282,11 @@
276282
:whitespace
277283
(do (.unreadChar stream c)
278284
true)
279-
(\, \] \} -1)
285+
(\, \] \})
280286
(do (.unreadChar stream c)
281287
true)
288+
-1
289+
true
282290
(throw (Exception. "JSON error (invalid number literal)")))
283291
;; previous character is a "e" or "E"
284292
:exp-symbol
@@ -306,9 +314,11 @@
306314
:whitespace
307315
(do (.unreadChar stream c)
308316
true)
309-
(\, \] \} -1)
317+
(\, \] \})
310318
(do (.unreadChar stream c)
311319
true)
320+
-1
321+
true
312322
(throw (Exception. "JSON error (invalid number literal)"))))))]
313323
(if decimal?
314324
(read-decimal (str buffer) bigdec?)

src/test/clojure/clojure/data/json_test.clj

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,24 @@
2727
(is (= {"foo" "some string"} (json/read pbr)))
2828
(is (= {"foo" "another long ......................................................... string"} (json/read pbr)))))
2929

30+
(defn read-then-eof [s]
31+
(let [r (pbr s)
32+
val (json/read r :eof-error? false :eof-value :EOF)]
33+
(is (= :EOF (json/read r :eof-error? false :eof-value :EOF)))
34+
val))
35+
36+
(deftest read-multiple-eof
37+
(are [expected s] (= expected (read-then-eof s))
38+
1.2 "1.2"
39+
0 "0"
40+
1 "1"
41+
1.0 "1.0"
42+
"abc" "\"abc\""
43+
"\u2202" "\"\u2202\""
44+
[] "[]"
45+
[1 2] "[1, 2]")
46+
)
47+
3048
(deftest read-from-reader
3149
(let [s (java.io.StringReader. "42")]
3250
(is (= 42 (json/read s)))))

0 commit comments

Comments
 (0)