2

我有一个解析数据流的系统,它需要根据许多用户的订阅来过滤它。然而,这些过滤器可以包含正则表达式,我需要使其足够安全,以便恶意用户无法插入故意消耗 CPU 开销的正则表达式以破坏服务。

我想知道最好的方法应该是什么,

在我制作的另一个程序中,我通过生成一个执行正则表达式搜索的新线程来处理这个问题,如果这个线程运行的时间超过了限制,它就会被杀死并且入口被阻止。

然而,这个系统可能每分钟处理数千条记录,我无法想象我会为每条记录生成一个新线程(实际上我需要为每个条目循环所有订阅,因此每分钟可能有数十万个线程) .

有没有更好的方法来处理这个问题?创建订阅后,我是否应该使用一些测试数据来测试正则表达式?或者可能为在不同线程中解析的每个用户使用单独的队列?

我想到的另一种方法是收集有关每个过滤器花费多少 CPU 时间的统计信息,并禁用那些消耗过多的过滤器,但这并不能真正处理可能需要几分钟 CPU 的“非常糟糕”的正则表达式完成时间

如果有人感兴趣,我正在用 c# 编写它,但这个问题相当笼统,可以适用于任何语言

4

4 回答 4

4

由于您使用的是 C#,因此您无需启动新线程。Regex构造函数有一个允许你设置timeout重载。如果正则表达式花费的时间太长,它将中止并抛出RegexMatchTimeoutException

For regex engines that do not have a built-in timeout, you would probably be able to manage by spawning only one thread and reusing it, or by letting the thread pool allocate the threads for you.

Another thing that would be worth doing if the regexes are more than a one-shot use is to compile the regexes. Regexes in C# support precompiling to speed up future matches.

于 2013-07-30T12:29:37.437 回答
1

如果你愿意实现自己的正则表达式引擎(或找一个库),请使用 Thompson 的 NFA 构造方法并限制每个自动机中的状态数(或者,为了更好的用户理解,高度相关的正则表达式的长度)。匹配算法的性能比回溯算法的性能更可预测。

于 2013-07-30T12:02:36.863 回答
1

我认为如果您在用户添加新过滤器时评估运行此正则表达式的成本会更好。例如:

  • 用户想要使用正则表达式添加过滤器 X。
  • 应用程序应在预定义的数据集上运行此过滤器。
  • 如果此运行时间超过 Y 毫秒,则不允许添加它。
  • 可以允许具有更高等级的用户(付费服务、忠诚用户……)更积极的过滤器(更多的处理毫秒)。
于 2013-07-30T12:08:59.853 回答
1

您实际上并不需要为每个正则表达式生成一个线程......相反,创建工作线程来处理循环中剩余的正则表达式,并在每次迭代时记录循环的开始。然后,使用您以前的解决方案来杀死耗时太长的工作线程,禁用正则表达式并重新生成工作线程。

这样,您就不必一直启动新线程的开销,但仍然可以杀死那些花费太长时间的线程。

于 2013-07-30T12:10:14.160 回答