summaryrefslogtreecommitdiff
path: root/src/papod.clj
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2026-04-26 09:54:01 -0300
committerEuAndreh <eu@euandre.org>2026-04-26 09:54:01 -0300
commit940399e10faa111ade4a2480a78d6ba692b7d603 (patch)
tree8206b37675fbbe275245b2cdf3ebe5847cba6d53 /src/papod.clj
parentImplement user mode +T (no CTCP) (diff)
downloadpapod-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.clj40
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))))))