Proof of concept mechanical port of ircnet/ircd to Rust as part of a bit about C being insecure for network services
3.0 kB
P11 slice 270 — enforce TOPICLEN on TOPIC set#
Goal#
leveva advertises TOPICLEN=255 in 005/ISUPPORT (isupport::TOPICLEN) but
command::topic records a TOPIC set of any length verbatim — the advertised
cap is cosmetic. charybdis/the IRCnet oracle enforce it by copying the new topic into
a fixed char topic[TOPICLEN+1] buffer (rb_strlcpy), i.e. silent truncation.
This slice makes leveva honour its own advertised TOPICLEN.
Locked decisions#
- Truncate, do not reject. Match charybdis: an over-length topic is silently cut
to the cap, not refused with a numeric. (There is no
ERR_*for "topic too long".) - Measured in Unicode grapheme clusters (UAX #29), not bytes. Consistent with
leveva's grapheme-based length policy:
LINELEN(slice 121) andMessage::to_wireboth count graphemes. A grapheme boundary is always acharboundary, so the cut is always valid UTF-8. - Enforced at the setting (home) server only. The local
TOPIChandler truncates once at the top, so the echo, the local-member fan-out, the stored topic, the later332query, and thes2s::relay::local_topicpropagation all carry the same truncated text. A topic arriving over S2S (relay::inbound_topic) is trusted — its origin already truncated it — exactly as charybdis trusts a remoteTOPIC.
Design#
isupport::truncate_topic(text: &str) -> &str— pure, returns the longest prefix oftextthat is at mostTOPICLENgrapheme clusters (the whole string when it already fits). Mirrors thegrapheme_indices(true).nth(LINELEN)cut inMessage::to_wire. Directly fuzzable.command::topic— in theSome(text)set branch,let text = truncate_topic(text);before it is used forset_topic/ theTOPICecho / the member fan-out / the relay.
Tests (RED first)#
command::topic:topic_set_truncates_to_topiclen— set aTOPICLEN + 50ASCII topic; the echo trailing and the later332query both carry exactlyTOPICLENgraphemes.topic_set_at_exactly_topiclen_is_untouched— aTOPICLENtopic survives whole.topic_set_truncates_multibyte_on_a_grapheme_boundary— an over-length multi-byte topic truncates to exactlyTOPICLENgraphemes and stays valid UTF-8.
isupport:truncate_topic_caps_and_passes_through— under/at/over the cap.- Fuzz
truncate_topic_proptest— for arbitrary input: result is a byte-prefix of the input, is ≤TOPICLENgraphemes, equals the input iff input ≤TOPICLENgraphemes, is idempotent, and is always valid UTF-8 (it is a&str).
Divergences#
- Grapheme cap, not byte cap. charybdis truncates by bytes; leveva by graphemes (its uniform length unit). For ASCII — the overwhelming common case — identical.
- Home-server enforcement only (above): inbound S2S topics are trusted, not re-truncated.
Gate#
cargo test -p leveva green; cargo clippy -p leveva --tests clean;
cargo build --workspace 0 warnings.