Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Now returns :SHORTCOUNT or :INVALID when parsing fails for either rea…

…son. Does the right thing for shortcounts inside of lists (which are actually invalid). Doesn't seem to blow up with lousy input
  • Loading branch information...
commit d410a9d614209a80d5c5dc5cb36ecbc465e7e072 1 parent 873aec1
@alexgartrell authored
Showing with 42 additions and 26 deletions.
  1. +32 −21 src/tnetstrings/core.clj
  2. +10 −5 test/tnetstrings/test/core.clj
View
53 src/tnetstrings/core.clj
@@ -6,13 +6,23 @@
;;; Helper functions for loads
(defn- explode-tnetstring [s]
- (let [[len-str data-plus] (.split s ":" 2)
- len (Integer. len-str)
- ; data-plus.length >= len + 1
- data (.substring data-plus 0 len)
- type (.charAt data-plus len)
- remains (.substring data-plus (+ len 1))]
- [data type remains]))
+ (if (or (neg? (.indexOf s (int \:))) (zero? (.length s)))
+ [:SHORTCOUNT :SHORTCOUNT s]
+ (try
+ (let [[len-str data-plus] (.split s ":" 2)
+ len (Integer. len-str)]
+ (if (or (neg? len) (> (+ len 1) (.length data-plus)))
+ [:SHORTCOUNT :SHORTCOUNT s]
+ (let
+ [data (.substring data-plus 0 len)
+ type (.charAt data-plus len)
+ remains (.substring data-plus (+ len 1))]
+ [data type remains])))
+ (catch java.lang.NumberFormatException e
+ [:INVALID :INVALID s]))))
+
+(defn- invalid-or-short? [ & rest ]
+ (not (not-any? (fn [x] (or (= x :INVALID) (= x :SHORTCOUNT))) rest)))
;; prototyping for the benefit of load-list and load-map
(defn- load-item [data type] nil)
@@ -26,7 +36,7 @@
(defn- load-bool [data]
(cond (= data "true") true
(= data "false") false
- :else :NOTMATCHED))
+ :else :INVALID))
(defn- load-list [data]
(loop [data data accum []]
@@ -34,9 +44,9 @@
(reverse accum)
(let [[data type remains] (explode-tnetstring data)
item (load-item data type)]
- (if (= item :NOTMATCHED)
- :NOTMATCHED
- (recur remains (cons (load-item data type) accum)))))))
+ (if (invalid-or-short? item)
+ :INVALID ; shortcounts cannot happen inside of valid lists
+ (recur remains (cons item accum)))))))
(defn- load-map [data]
(loop [data data accum {}]
@@ -46,19 +56,20 @@
[vdata vtype remains] (explode-tnetstring val-plus)
key (load-item kdata ktype)
val (load-item vdata vtype)]
- (if (or (= key :NOTMATCHED) (= val :NOTMATCHED))
- :NOTMATCHED
+ (if (invalid-or-short? key val)
+ :INVALID ; shortcounts cannot happen inside of valid maps
(recur remains (assoc accum key val)))))))
(defn- load-item [data type]
(let [tis (fn [t] (= type t))] ; Abbreviating (= type t) to (tis t)
- (cond (tis \~) nil ; Null
- (tis \,) (load-str data) ; String
- (tis \#) (load-int data) ; Integer
- (tis \!) (load-bool data) ; Boolean
- (tis \]) (load-list data) ; List
- (tis \}) (load-map data) ; Map
- :else :NOTMATCHED)))
+ (cond (tis \~) nil ; Null
+ (tis \,) (load-str data) ; String
+ (tis \#) (load-int data) ; Integer
+ (tis \!) (load-bool data) ; Boolean
+ (tis \]) (load-list data) ; List
+ (tis \}) (load-map data) ; Map
+ (tis :SHORTCOUNT) :SHORTCOUNT ; Short Count
+ :else :INVALID)))
;;; Helper functions for dumps
@@ -98,7 +109,7 @@
(boolean? item) (dump-bool item) ; Boolean
(list? item) (dump-list item) ; List
(map? item) (dump-map item) ; Map
- :else :NOTMATCHED))
+ :else :INVALID))
;;; Public Functions
View
15 test/tnetstrings/test/core.clj
@@ -37,12 +37,17 @@
(is (= "25:3:foo,3:bar,3:biz,4:bang,}"
(dumps {"foo" "bar" "biz" "bang"})))))
-;; This needs a lot of work, both here and in the actual core, we pretty much
-;; puke whenever something has a bad prefix length
(deftest malformed-loads
- (is (= :NOTMATCHED (loads "3:foo!")))
- (is (= :NOTMATCHED (loads "6:3:foo!]")))
- (is (= :NOTMATCHED (loads "10:1:1#3:foo!]"))))
+ (is (= :INVALID (loads "3:foo!")))
+ (is (= :INVALID (loads "6:3:foo!]")))
+ (is (= :INVALID (loads "10:1:1#3:foo!]")))
+ (is (= :INVALID (loads "4:10:aa]")))
+ (is (= :INVALID (loads "foo:"))))
+
+(deftest shortcount-loads
+ (is (= :SHORTCOUNT (loads "10:aaaaaaaaaa")))
+ (is (= :SHORTCOUNT (loads "1")))
+ (is (= :SHORTCOUNT (loads ""))))
(defn roundtrip-item [item]
(is (= item (loads (dumps item)))))
Please sign in to comment.
Something went wrong with that request. Please try again.