mirror of
https://github.com/2dust/v2rayN.git
synced 2026-09-22 22:38:10 +03:00
Filter patterns (subscription subFilter, policy-group Filter, message MsgFilter) accept arbitrary user input while the tested text (remarks from subscriptions, log lines) is attacker-influenced. Regex.IsMatch without timeout hangs on evil patterns like (a+)+$ - a malicious subscription can freeze the UI/log pipeline on every update. Add Utils.IsRegexMatch with a 2s timeout; fail open (match) with a log so no node or message is silently dropped. Apply to all four call sites. Co-authored-by: sdhfsl <sdhfsl@users.noreply.github.com>
120 lines
2.9 KiB
C#
120 lines
2.9 KiB
C#
namespace ServiceLib.ViewModels;
|
|
|
|
public partial class MsgViewModel : MyReactiveObject
|
|
{
|
|
public Interaction<string, RxVoid> ShowMsgInteraction { get; } = new();
|
|
|
|
private readonly ConcurrentQueue<string> _queueMsg = new();
|
|
private volatile bool _lastMsgFilterNotAvailable;
|
|
public int NumMaxMsg => 500;
|
|
|
|
[Reactive]
|
|
public partial string MsgFilter { get; set; }
|
|
|
|
[Reactive]
|
|
public partial bool AutoRefresh { get; set; }
|
|
|
|
public MsgViewModel()
|
|
{
|
|
_config = AppManager.Instance.Config;
|
|
MsgFilter = _config.MsgUIItem.MainMsgFilter ?? string.Empty;
|
|
AutoRefresh = _config.MsgUIItem.AutoRefresh ?? true;
|
|
|
|
this.WhenAnyValue(
|
|
x => x.MsgFilter)
|
|
.Subscribe(c => DoMsgFilter());
|
|
|
|
this.WhenAnyValue(x => x.AutoRefresh)
|
|
.Subscribe(_ => _config.MsgUIItem.AutoRefresh = AutoRefresh);
|
|
|
|
AppEvents.SendMsgViewRequested
|
|
.AsObservable()
|
|
.Subscribe(EnqueueQueueMsg);
|
|
|
|
this.WhenActivated(disposables =>
|
|
{
|
|
Signal.Every(TimeSpan.FromSeconds(1))
|
|
.Where(_ => AutoRefresh && AppManager.Instance.ShowInTaskbar)
|
|
.ObserveOn(RxSchedulers.MainThreadScheduler)
|
|
.Subscribe(_ => FlushQueueToView())
|
|
.DisposeWith(disposables);
|
|
});
|
|
}
|
|
|
|
private void FlushQueueToView()
|
|
{
|
|
if (!AutoRefresh || _queueMsg.IsEmpty)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!AppManager.Instance.ShowInTaskbar)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var sb = new StringBuilder();
|
|
while (_queueMsg.TryDequeue(out var msg))
|
|
{
|
|
sb.Append(msg);
|
|
}
|
|
|
|
if (sb.Length > 0)
|
|
{
|
|
ShowMsgInteraction.HandleSafe(sb.ToString()).Subscribe();
|
|
}
|
|
}
|
|
|
|
private void EnqueueQueueMsg(string msg)
|
|
{
|
|
if (string.IsNullOrEmpty(msg))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//filter msg
|
|
if (MsgFilter.IsNotEmpty() && !_lastMsgFilterNotAvailable)
|
|
{
|
|
try
|
|
{
|
|
if (!Utils.IsRegexMatch(msg, MsgFilter))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
EnqueueWithLimit(ex.Message);
|
|
_lastMsgFilterNotAvailable = true;
|
|
}
|
|
}
|
|
|
|
var formattedMsg = msg.EndsWith(Environment.NewLine)
|
|
? msg
|
|
: msg + Environment.NewLine;
|
|
|
|
EnqueueWithLimit(formattedMsg);
|
|
}
|
|
|
|
private void EnqueueWithLimit(string item)
|
|
{
|
|
_queueMsg.Enqueue(item);
|
|
|
|
while (_queueMsg.Count > NumMaxMsg)
|
|
{
|
|
_queueMsg.TryDequeue(out _);
|
|
}
|
|
}
|
|
|
|
//public void ClearMsg()
|
|
//{
|
|
// _queueMsg.Clear();
|
|
//}
|
|
|
|
private void DoMsgFilter()
|
|
{
|
|
_config.MsgUIItem.MainMsgFilter = MsgFilter;
|
|
_lastMsgFilterNotAvailable = false;
|
|
}
|
|
}
|