Skip to content

Commit

Permalink
DJSON-57 Throw better exception on EOF in object or array reading
Browse files Browse the repository at this point in the history
  • Loading branch information
puredanger committed Dec 21, 2023
1 parent d694575 commit 8661733
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ Change Log
* Next
* Fix [DJSON-50]: `read` can take a PushbackReader for repeated read use case
* Fix `write` docstring to add `:indent` option added in [DJSON-18]
* Fix [DJSON-57]: Throw better exception when EOF encountered while reading array or object
* Add [DJSON-46]: In `read`, add `:extra-data-fn` that can be provided to cause an eof check after value is read
* Add [DJSON-54]: In `write`, add custom fallback fn for writing unknown types
* Perf [DJSON-61]: Faster string writing when string is "simple"
Expand Down Expand Up @@ -246,6 +247,7 @@ Change Log
* Source-compatible with clojure.contrib.json, except for the name change.

[DJSON-61]: https://clojure.atlassian.net/browse/DJSON-61
[DJSON-57]: https://clojure.atlassian.net/browse/DJSON-57
[DJSON-54]: https://clojure.atlassian.net/browse/DJSON-54
[DJSON-53]: https://clojure.atlassian.net/browse/DJSON-53
[DJSON-52]: https://clojure.atlassian.net/browse/DJSON-52
Expand Down
25 changes: 23 additions & 2 deletions src/main/clojure/clojure/data/json.clj
Original file line number Diff line number Diff line change
Expand Up @@ -325,13 +325,17 @@
(defn invalid-array-exception []
(Exception. "JSON error (invalid array)"))

(defn- eof-array-exception []
(EOFException. "JSON error (EOF in array)"))

(defn- read-array* [^InternalPBR stream options]
;; Handles all array values after the first.
(loop [result (transient [])]
(let [r (conj! result (-read stream true nil options))]
(codepoint-case (int (next-token stream))
\] (persistent! r)
\, (recur r)
-1 (throw (eof-array-exception))
(throw (invalid-array-exception))))))

(defn- read-array [^InternalPBR stream options]
Expand All @@ -342,19 +346,35 @@
(codepoint-case c
\] []
\, (throw (invalid-array-exception))
-1 (throw (eof-array-exception))
(do (.unreadChar stream c)
(read-array* stream options)))))

(defn- object-colon-exception []
(Exception. "JSON error (missing `:` in object)"))

(defn- eof-object-exception []
(EOFException. "JSON error (EOF in object)"))

(defn- invalid-key-exception [c]
(if (= c -1)
(throw (eof-object-exception))
(throw (Exception. (str "JSON error (non-string key in object), found `" (char c) "`, expected `\"`")))))

(comment
(compile 'clojure.data.json)
)

(defn- read-key [^InternalPBR stream]
(let [c (int (next-token stream))]
(if (= c (codepoint \"))
(let [key (read-quoted-string stream)]
(if (= (codepoint \:) (int (next-token stream)))
key
(throw (Exception. "JSON error (missing `:` in object)"))))
(throw (object-colon-exception))))
(if (= c (codepoint \}))
nil
(throw (Exception. (str "JSON error (non-string key in object), found `" (char c) "`, expected `\"`")))))))
(invalid-key-exception c)))))

(defn- read-object [^InternalPBR stream options]
;; Expects to be called with the head of the stream AFTER the
Expand All @@ -374,6 +394,7 @@
(codepoint-case (int (next-token stream))
\, (recur r)
\} (persistent! r)
-1 (throw (eof-object-exception))
(throw (Exception. "JSON error (missing entry in object)"))))
(let [r (persistent! result)]
(if (empty? r)
Expand Down
12 changes: 12 additions & 0 deletions src/test/clojure/clojure/data/json_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,18 @@
(is (thrown? java.io.EOFException
(json/read-str "\"\\"))))

(deftest throws-eof-in-arrays
(is (thrown? java.io.EOFException
(json/read-str "[1,")))
(is (thrown? java.io.EOFException
(json/read-str "[1,2,"))))

(deftest throws-eof-in-objects
(is (thrown? java.io.EOFException
(json/read-str "{")))
(is (thrown? java.io.EOFException
(json/read-str "{\"\":1,"))))

(deftest accept-eof
(is (= ::eof (json/read-str "" :eof-error? false :eof-value ::eof))))

Expand Down

0 comments on commit 8661733

Please sign in to comment.