fix: regex injection in message search + semaphore expect panic
- Escape regex special chars in highlightText to prevent ReDoS - Replace semaphore.acquire().expect() with graceful skip - Add toast error feedback for search failures - Remove unsafe (resp.data as any) bypass
This commit is contained in:
parent
2842a62d35
commit
1e975c0837
@ -207,7 +207,10 @@ where
|
||||
let semaphore = worker_semaphore.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
let _permit = semaphore.acquire().await.expect("semaphore closed");
|
||||
let Ok(_permit) = semaphore.acquire().await else {
|
||||
tracing::warn!(task_id = %task_id, "semaphore closed, skipping task");
|
||||
return;
|
||||
};
|
||||
|
||||
let result = execute(task_id, task_service.clone()).await;
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import { ScrollArea } from '@/components/ui/scroll-area';
|
||||
import { Search, X, Loader2, ArrowUp } from 'lucide-react';
|
||||
import { client } from '@/client/client.gen';
|
||||
import type { RoomMessageResponse } from '@/client';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
interface SearchResult {
|
||||
messages: RoomMessageResponse[];
|
||||
@ -40,13 +41,13 @@ export function RoomMessageSearch({ roomId, onSelectMessage, onClose }: RoomMess
|
||||
url: `/api/rooms/${roomId}/messages/search`,
|
||||
params: { q: searchQuery, limit: 20, offset: searchOffset },
|
||||
});
|
||||
const data = (resp.data as any)?.data as SearchResult | undefined;
|
||||
const data = resp.data?.data as SearchResult | undefined;
|
||||
if (data) {
|
||||
setResults(data);
|
||||
setOffset(searchOffset);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Search failed:', err);
|
||||
toast.error('Search failed. Please try again.');
|
||||
} finally {
|
||||
setIsSearching(false);
|
||||
}
|
||||
@ -66,9 +67,11 @@ export function RoomMessageSearch({ roomId, onSelectMessage, onClose }: RoomMess
|
||||
|
||||
const highlightText = (text: string, searchQuery: string) => {
|
||||
if (!searchQuery.trim()) return text;
|
||||
const regex = new RegExp(`(${searchQuery})`, 'gi');
|
||||
// Escape regex special characters to prevent regex injection / ReDoS.
|
||||
const escaped = searchQuery.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
const regex = new RegExp(`(${escaped})`, 'gi');
|
||||
const parts = text.split(regex);
|
||||
return parts.map((part, i) =>
|
||||
return parts.map((part, i) =>
|
||||
regex.test(part) ? (
|
||||
<mark key={i} className="bg-yellow-200 text-inherit">{part}</mark>
|
||||
) : (
|
||||
|
||||
Loading…
Reference in New Issue
Block a user