From 3e5043f875fb6819a74274dbf6c3403f4c5d061f Mon Sep 17 00:00:00 2001 From: jack Date: Thu, 28 Aug 2025 09:22:34 +0100 Subject: [PATCH] Harden text formatting against Unicode range mismatches - Use NSString.length for all NSRange regex scans - Guard string slicing when lastEnd > match.lowerBound - Advance lastEnd safely to avoid backtracking overlaps - Apply to formatMessageContent, formatMessage, formatMessageAsText, parseMentions --- bitchat/ViewModels/ChatViewModel.swift | 46 ++++++++++++++++---------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/bitchat/ViewModels/ChatViewModel.swift b/bitchat/ViewModels/ChatViewModel.swift index 03b18761..0c6303e9 100644 --- a/bitchat/ViewModels/ChatViewModel.swift +++ b/bitchat/ViewModels/ChatViewModel.swift @@ -3043,8 +3043,10 @@ class ChatViewModel: ObservableObject, BitchatDelegate { let mentionRegex = try? NSRegularExpression(pattern: mentionPattern, options: []) let hashtagRegex = try? NSRegularExpression(pattern: hashtagPattern, options: []) - let mentionMatches = mentionRegex?.matches(in: contentText, options: [], range: NSRange(location: 0, length: contentText.count)) ?? [] - let hashtagMatches = hashtagRegex?.matches(in: contentText, options: [], range: NSRange(location: 0, length: contentText.count)) ?? [] + let nsContent = contentText as NSString + let nsLen = nsContent.length + let mentionMatches = mentionRegex?.matches(in: contentText, options: [], range: NSRange(location: 0, length: nsLen)) ?? [] + let hashtagMatches = hashtagRegex?.matches(in: contentText, options: [], range: NSRange(location: 0, length: nsLen)) ?? [] // Combine and sort all matches var allMatches: [(range: NSRange, type: String)] = [] @@ -3061,12 +3063,14 @@ class ChatViewModel: ObservableObject, BitchatDelegate { for (matchRange, matchType) in allMatches { // Add text before the match if let range = Range(matchRange, in: contentText) { - let beforeText = String(contentText[lastEndIndex..