Add optional max-size param to blob decode functions

Accept an optional :max-size keyword argument in blob/decode and
blob/decode-str. When provided, the uncompressed size declared in the
blob header is validated before allocating memory, raising an error if
it exceeds the limit. Callers that do not pass :max-size are unaffected.

AI-assisted-by: deepseek-v4-pro
This commit is contained in:
Andrey Antukh 2026-08-04 15:38:22 +00:00
parent c16b7919f9
commit 3e59754a25

View File

@ -8,6 +8,7 @@
"A generic blob storage encoding. Mainly used for page data, page "A generic blob storage encoding. Mainly used for page data, page
options and txlog payload storage." options and txlog payload storage."
(:require (:require
[app.common.exceptions :as ex]
[app.common.fressian :as fres] [app.common.fressian :as fres]
[app.common.transit :as t] [app.common.transit :as t]
[app.config :as cf]) [app.config :as cf])
@ -58,12 +59,18 @@
(.encodeToString (.withoutPadding (Base64/getUrlEncoder)) ^bytes (encode data opts)))) (.encodeToString (.withoutPadding (Base64/getUrlEncoder)) ^bytes (encode data opts))))
(defn decode (defn decode
"A function used for decode persisted blobs in the database." "A function used for decode persisted blobs in the database.
[^bytes data] Accepts optional keyword arguments:
:max-size maximum allowed uncompressed size in bytes"
[^bytes data & {:keys [max-size]}]
(with-open [bais (ByteArrayInputStream. data) (with-open [bais (ByteArrayInputStream. data)
dis (DataInputStream. bais)] dis (DataInputStream. bais)]
(let [version (.readShort dis) (let [version (.readShort dis)
ulen (.readInt dis)] ulen (.readInt dis)]
(when (and max-size (> ulen max-size))
(ex/raise :type :validation
:code :blob-too-large
:hint "blob uncompressed size exceeds limit"))
(case version (case version
1 (decode-v1 data ulen) 1 (decode-v1 data ulen)
3 (decode-v3 data ulen) 3 (decode-v3 data ulen)
@ -72,9 +79,10 @@
(throw (ex-info "unsupported version" {:version version})))))) (throw (ex-info "unsupported version" {:version version}))))))
(defn decode-str (defn decode-str
"Decode a URL-safe base64 string produced by `encode-str` back to data." "Decode a URL-safe base64 string produced by `encode-str` back to data.
[^String s] Accepts the same optional keyword arguments as `decode`."
(decode (.decode (Base64/getUrlDecoder) s))) [^String s & {:as opts}]
(decode (.decode (Base64/getUrlDecoder) s) opts))
;; --- IMPL ;; --- IMPL