diff options
| author | EuAndreh <eu@euandre.org> | 2026-04-26 09:54:01 -0300 |
|---|---|---|
| committer | EuAndreh <eu@euandre.org> | 2026-04-26 09:54:01 -0300 |
| commit | 940399e10faa111ade4a2480a78d6ba692b7d603 (patch) | |
| tree | 8206b37675fbbe275245b2cdf3ebe5847cba6d53 /src/papod.clj | |
| parent | Implement user mode +T (no CTCP) (diff) | |
| download | papod-940399e10faa111ade4a2480a78d6ba692b7d603.tar.gz papod-940399e10faa111ade4a2480a78d6ba692b7d603.tar.xz | |
Truncate outgoing lines to 512 bytes; safe UTF-8 input handling
Outgoing: cap line at 512 bytes including CRLF, never split a multi-byte
UTF-8 character; 510-byte payload limit + truncate-utf8-bytes helper.
Incoming: read via InputStreamReader (UTF-8) so byte-per-byte input
doesn't decode partial multi-byte sequences as U+FFFD.
Diffstat (limited to 'src/papod.clj')
| -rw-r--r-- | src/papod.clj | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/src/papod.clj b/src/papod.clj index 6e53997..5e81533 100644 --- a/src/papod.clj +++ b/src/papod.clj @@ -848,11 +848,39 @@ [?m :papod.memo/read? false]]} (d/db conn) nick)))) +(defn- truncate-utf8-bytes + ^bytes [^bytes bytes max-len] + (let [n (alength bytes)] + (if (<= n max-len) + bytes + (loop [i 0] + (if (>= i n) + bytes + (let [b (bit-and (aget bytes i) 0xff) + len (cond + (zero? (bit-and b 0x80)) 1 + (= (bit-and b 0xe0) 0xc0) 2 + (= (bit-and b 0xf0) 0xe0) 3 + (= (bit-and b 0xf8) 0xf0) 4 + :else 1) + end (+ i len)] + (if (or (> end n) (> end max-len)) + (java.util.Arrays/copyOfRange bytes 0 i) + (recur end)))))))) + (defn- deliver-to-client! [w line] (try - (let [bytes (.getBytes (str line +delimiter+) +charset+)] - (.write w bytes 0 (count bytes)) + (let [body (.getBytes (str line) +charset+) + delim (.getBytes +delimiter+ +charset+) + body' (truncate-utf8-bytes body + (- 512 (alength delim))) + out (byte-array (+ (alength body') + (alength delim)))] + (System/arraycopy body' 0 out 0 (alength body')) + (System/arraycopy delim 0 out (alength body') + (alength delim)) + (.write w out 0 (alength out)) (.flush w)) (catch Exception _))) @@ -3824,9 +3852,11 @@ (when s (.setSoTimeout s (int +idle-timeout-ms+)))) (catch Exception _)) - r (java.nio.channels.Channels/newInputStream socket) + r (java.io.InputStreamReader. + (java.nio.channels.Channels/newInputStream socket) + +charset+) w (java.nio.channels.Channels/newOutputStream socket) - b (make-array Byte/TYPE +buffer-size+) + b (char-array +buffer-size+) conn-id (java.util.UUID/randomUUID) client (atom {:nick nil :user nil :pass nil :registered? false :w w :connection-id conn-id @@ -3844,7 +3874,7 @@ (let [n (.read r b)] (when (pos? n) (let [new-acc (process-input! - (str acc (String. b 0 n +charset+)) + (str acc (String. b 0 n)) w client components)] (when-not (:quit? @client) (recur new-acc)))))) |
