recursive/embedded version of issue/907;

test cases merged from remote-tracking branch 'yarikoptic:enh/embedded_tags' into issue/907
infinite busy loop on _escapedTags match in substituteRecursiveTags gh-907
pull/919/head
sebres 2015-01-20 17:09:13 +01:00
parent b04a51246f
commit 33e9e2174a
3 changed files with 42 additions and 27 deletions

View File

@ -30,6 +30,9 @@ ver. 0.9.2 (2014/XX/XXX) - wanna-be-released
- New Features:
- New filter:
- postfix-rbl Thanks Lee Clemens
- New recursive embedded substitution feature added:
- `<<PREF>HOST>` becomes `<IPV4HOST>` for PREF=`IPV4`;
- `<<PREF>HOST>` becomes `1.2.3.4` for PREF=`IPV4` and IPV4HOST=`1.2.3.4`;
- New interpolation feature for config readers - `%(known/parameter)s`.
(means last known option with name `parameter`). This interpolation makes
possible to extend a stock filter or jail regexp in .local file

View File

@ -378,34 +378,41 @@ class CommandAction(ActionBase):
Dictionary of tags(keys) and their values, with tags
within the values recursively replaced.
"""
t = re.compile(r'<([^ >]+)>')
for tag in tags.iterkeys():
if tag in cls._escapedTags:
# Escaped so won't match
continue
value = str(tags[tag])
m = t.search(value)
done = []
#logSys.log(5, 'TAG: %s, value: %s' % (tag, value))
while m:
found_tag = m.group(1)
#logSys.log(5, 'found: %s' % found_tag)
if found_tag == tag or found_tag in done:
# recursive definitions are bad
#logSys.log(5, 'recursion fail tag: %s value: %s' % (tag, value) )
return False
if found_tag in cls._escapedTags or not tags.has_key(found_tag):
# Escaped or missing tags - just continue on searching after end of match
# Missing tags are ok - cInfo can contain aInfo elements like <HOST> and valid shell
# constructs like <STDIN>.
m = t.search(value, m.end())
t = re.compile(r'<([^ <>]+)>')
while True:
repFlag = False
for tag in tags.iterkeys():
if tag in cls._escapedTags:
# Escaped so won't match
continue
value = value.replace('<%s>' % found_tag , tags[found_tag])
#logSys.log(5, 'value now: %s' % value)
done.append(found_tag)
m = t.search(value, m.start())
#logSys.log(5, 'TAG: %s, newvalue: %s' % (tag, value))
tags[tag] = value
value = str(tags[tag])
m = t.search(value)
done = []
#logSys.log(5, 'TAG: %s, value: %s' % (tag, value))
while m:
found_tag = m.group(1)
#logSys.log(5, 'found: %s' % found_tag)
if found_tag == tag or found_tag in done:
# recursive definitions are bad
#logSys.log(5, 'recursion fail tag: %s value: %s' % (tag, value) )
return False
if found_tag in cls._escapedTags or not tags.has_key(found_tag):
# Escaped or missing tags - just continue on searching after end of match
# Missing tags are ok - cInfo can contain aInfo elements like <HOST> and valid shell
# constructs like <STDIN>.
m = t.search(value, m.end())
continue
value = value.replace('<%s>' % found_tag , tags[found_tag])
#logSys.log(5, 'value now: %s' % value)
done.append(found_tag)
m = t.search(value, m.start())
#logSys.log(5, 'TAG: %s, newvalue: %s' % (tag, value))
# if was substituted, check again later:
if tags[tag] != value:
repFlag = True
tags[tag] = value
if not repFlag:
break
return tags
@staticmethod

View File

@ -73,6 +73,11 @@ class CommandActionTest(LogCaptureTestCase):
'ABC': '123 192.0.2.0',
'xyz': '890 123 192.0.2.0',
})
# obscure embedded case
self.assertEqual(CommandAction.substituteRecursiveTags({'A': '<<PREF>HOST>', 'PREF': 'IPV4'}),
{'A': '<IPV4HOST>', 'PREF': 'IPV4'})
self.assertEqual(CommandAction.substituteRecursiveTags({'A': '<<PREF>HOST>', 'PREF': 'IPV4', 'IPV4HOST': '1.2.3.4'}),
{'A': '1.2.3.4', 'PREF': 'IPV4', 'IPV4HOST': '1.2.3.4'})
def testReplaceTag(self):
aInfo = {