r")"
% "|".join(actions))
+class NoEndOfOptionError(Exception):
+ """Exception raised when the end of option terminator (semicolon) is
+ missing."""
+ pass
+
class Rule(dict):
"""Class representing a rule.
if not options:
break
index = find_opt_end(options)
+ if index < 0:
+ raise NoEndOfOptionError("no end of option")
option = options[:index].strip()
options = options[index + 1:].strip()
if line.rstrip().endswith("\\"):
buf = "%s%s " % (buf, line.rstrip()[0:-1])
continue
+ buf = buf + line
try:
- rule = parse(buf + line, group)
+ rule = parse(buf, group)
if rule:
rules.append(rule)
- except:
- logger.error("failed to parse rule: %s" % (buf))
- raise
+ except Exception as err:
+ logger.error("Failed to parse rule: %s: %s", buf.rstrip(), err)
buf = ""
return rules
self.assertIsNotNone(rule)
self.assertTrue("former_category TROJAN" in rule.metadata)
self.assertTrue("updated_at 2017_08_08" in rule.metadata)
+
+ def test_parse_option_missing_end(self):
+ """Test parsing a rule where the last option is missing a
+ semicolon. This was responsible for an infinite loop. """
+ rule_buf = u"""alert icmp any any -> $HOME_NET any (msg:"ICMP test detected"; gid:0; sid:10000001; rev:1; classtype: icmp-event; metadata:policy balanced-ips drop, policy connectivity-ips drop, policy security-ips drop)"""
+ self.assertRaises(
+ suricata.update.rule.NoEndOfOptionError,
+ suricata.update.rule.parse, rule_buf)