Secure some more commands which take a regexp from untrusted user input.

Namely todo.search, note.search, dunno.search.

Signed-off-by: James McCoy <jamessan@users.sourceforge.net>
This commit is contained in:
Daniel Folkinshteyn 2011-08-12 18:10:41 -04:00 committed by James McCoy
parent ac500b059a
commit 18ec61842c
4 changed files with 26 additions and 2 deletions

View File

@ -35,6 +35,7 @@ import operator
import supybot.dbi as dbi
import supybot.log as log
import supybot.conf as conf
from supybot import commands
import supybot.utils as utils
import supybot.ircdb as ircdb
from supybot.commands import *
@ -292,7 +293,8 @@ class Note(callbacks.Plugin):
own = to
for (option, arg) in optlist:
if option == 'regexp':
criteria.append(arg.search)
criteria.append(lambda x: commands.regexp_wrapper(x, reobj=arg,
timeout=0.1, plugin_name=self.name(), fcn_name='search'))
elif option == 'sent':
own = frm
if glob:

View File

@ -35,6 +35,7 @@ import operator
import supybot.dbi as dbi
import supybot.conf as conf
from supybot import commands
import supybot.ircdb as ircdb
import supybot.utils as utils
from supybot.commands import *
@ -228,6 +229,8 @@ class Todo(callbacks.Plugin):
criteria = []
for (option, arg) in optlist:
if option == 'regexp':
criteria.append(lambda x: commands.regexp_wrapper(x, reobj=arg,
timeout=0.1, plugin_name=self.name(), fcn_name='search'))
criteria.append(arg.search)
for glob in globs:
glob = utils.python.glob2re(glob)

View File

@ -419,7 +419,8 @@ class ChannelIdDatabasePlugin(callbacks.Plugin):
if opt == 'by':
predicates.append(lambda r, arg=arg: r.by == arg.id)
elif opt == 'regexp':
predicates.append(lambda r, arg=arg: arg.search(r.text))
predicates.append(lambda x: regexp_wrapper(x.text, reobj=arg,
timeout=0.1, plugin_name=self.name(), fcn_name='search'))
if glob:
def globP(r, glob=glob.lower()):
return fnmatch.fnmatch(r.text.lower(), glob)

View File

@ -98,6 +98,24 @@ def process(f, *args, **kwargs):
v = "Error: " + str(v)
return v
def regexp_wrapper(s, reobj, timeout, plugin_name, fcn_name):
'''A convenient wrapper to stuff regexp search queries through a subprocess.
This is used because specially-crafted regexps can use exponential time
and hang the bot.'''
def re_bool(s, reobj):
"""Since we can't enqueue match objects into the multiprocessing queue,
we'll just wrap the function to return bools."""
if reobj.search(s) is not None:
return True
else:
return False
try:
v = process(re_bool, s, reobj, timeout=timeout, pn=plugin_name, cn=fcn_name)
return v
except ProcessTimeoutError:
return False
class UrlSnarfThread(world.SupyThread):
def __init__(self, *args, **kwargs):
assert 'url' in kwargs