Beispiel #1
0
    def testPrefixMinus(self):
        query = "-(5 + 5)"
        expected = expression.Product(
            expression.Literal(-1),
            expression.Sum(expression.Literal(5), expression.Literal(5)))

        self.assertQueryMatches(query, expected)
Beispiel #2
0
    def testPrefixMinusLowPrecedence(self):
        query = "-5 * 5"
        expected = expression.Product(
            expression.Literal(-1),
            expression.Product(expression.Literal(5), expression.Literal(5)))

        self.assertQueryMatches(query, expected)
Beispiel #3
0
    def testParens(self):
        query = "(3 + 2) * 5"
        expected = expression.Product(
            expression.Sum(expression.Literal(3), expression.Literal(2)),
            expression.Literal(5))

        self.assertQueryMatches(query, expected)
Beispiel #4
0
    def testLists(self):
        query = "'foo' in ('foo', 'bar') and 1 not in (5, 2, 3,17)"
        expected = expression.Intersection(
            expression.Membership(expression.Literal("foo"),
                                  expression.Literal(("foo", "bar"))),
            expression.Complement(
                expression.Membership(expression.Literal(1),
                                      expression.Literal((5, 2, 3, 17)))))

        self.assertQueryMatches(query, expected)
Beispiel #5
0
 def testPrecedence(self):
     query = "5 == 1 * 5 and Process/name is 'init'"
     expected = expression.Intersection(
         expression.Equivalence(
             expression.Literal(5),
             expression.Product(expression.Literal(1),
                                expression.Literal(5))),
         expression.Equivalence(expression.Binding("Process/name"),
                                expression.Literal("init")))
     self.assertQueryMatches(query, expected)
Beispiel #6
0
    def testLetSubexpr(self):
        query = ("Process/parent matches (Process/command is 'init' and "
                 "Process/pid is 1)")
        expected = expression.Let(
            expression.Binding("Process/parent"),
            expression.Intersection(
                expression.Equivalence(expression.Binding("Process/command"),
                                       expression.Literal("init")),
                expression.Equivalence(expression.Binding("Process/pid"),
                                       expression.Literal(1))))

        self.assertQueryMatches(query, expected)
Beispiel #7
0
    def testParamFailures(self):
        query = "{foo} == 1"
        params = ["Process/pid"]
        self.assertQueryRaises(query, params=params)

        # Even fixing the above, the left side should be a literal, not a
        # binding.
        query = "{foo} == 1"
        params = {"foo": "Process/pid"}
        exptected = expression.Equivalence(expression.Literal("Process/pid"),
                                           expression.Literal(1))
        self.assertQueryMatches(query, exptected, params=params)
Beispiel #8
0
    def testTemplateReplacements(self):
        query = "Process/pid == {}"
        params = [1]
        exptected = expression.Equivalence(expression.Binding("Process/pid"),
                                           expression.Literal(1))
        self.assertQueryMatches(query, exptected, params=params)

        query = "Process/pid == {pid}"
        params = {"pid": 1}
        exptected = expression.Equivalence(expression.Binding("Process/pid"),
                                           expression.Literal(1))
        self.assertQueryMatches(query, exptected, params=params)
Beispiel #9
0
    def _solve_equivalence(self, expr, binding, literal):
        literal_value = literal.value
        if isinstance(literal_value, entity_id.Identity):
            results = set()
            for index in literal_value.indices:
                results |= self._solve_equivalence(expr, binding,
                                                   expression.Literal(index))

            return results

        table = self.lookup_tables.get(binding.value, None)
        if table:
            # Sweet, we have exact index for this.
            return self._as_entities(table.table.get(literal_value, set()))

        # Don't have an exact index, but can prefilter by component index.
        component, _ = binding.value.split("/", 1)
        slow_matcher = matcher.ObjectMatcher(self._subquery(expr))
        entities = set()
        candidates = self.lookup_tables["components"].table.get(component, [])
        for identity in candidates:
            entity = self.entities[identity.first_index]
            if slow_matcher.run(entity):
                entities.add(entity)

        return entities
Beispiel #10
0
    def testLetSubexprEach(self):
        query = "each Process/children matches Process/command is 'foo'"
        expected = expression.LetEach(
            expression.Binding("Process/children"),
            expression.Equivalence(expression.Binding("Process/command"),
                                   expression.Literal("foo")))

        self.assertQueryMatches(query, expected)
Beispiel #11
0
    def testLetSingleAny(self):
        query = "any Process/parent->Process/command is 'init'"
        expected = expression.LetAny(
            expression.Binding("Process/parent"),
            expression.Equivalence(expression.Binding("Process/command"),
                                   expression.Literal("init")))

        self.assertQueryMatches(query, expected)
Beispiel #12
0
    def testBigQuery(self):
        query = ("(Process/pid is 1 and Process/command in ('init', 'initd')) "
                 "or any Process/children matches (Process/command not in "
                 "('launchd', 'foo'))")
        expected = expression.Union(
            expression.Intersection(
                expression.Equivalence(expression.Binding("Process/pid"),
                                       expression.Literal(1)),
                expression.Membership(expression.Binding("Process/command"),
                                      expression.Literal(("init", "initd")))),
            expression.LetAny(
                expression.Binding("Process/children"),
                expression.Complement(
                    expression.Membership(
                        expression.Binding("Process/command"),
                        expression.Literal(("launchd", "foo"))))))

        self.assertQueryMatches(query, expected)
Beispiel #13
0
    def testLetSingle(self):
        query = "ProcessParent matches ProcessCommand is 'init'"
        expected = expression.Let(
            expression.Binding("ProcessParent"),
            expression.Equivalence(
                expression.Binding("ProcessCommand"),
                expression.Literal("init")))

        self.assertQueryMatches(query, expected)
Beispiel #14
0
    def as_query(self):
        """A query that'll match entities with this identity."""
        union = []
        for _, keys, vals in self.indices:
            if isinstance(keys, tuple):
                intersection = []
                for idx, key in enumerate(keys):
                    intersection.append(
                        expression.Equivalence(expression.Binding(key),
                                               expression.Literal(vals[idx])))

                union.append(expression.Intersection(*intersection))
            else:
                union.append(
                    expression.Equivalence(expression.Binding(keys),
                                           expression.Literal(vals)))

        if len(union) == 1:
            return union[0]

        return expression.Union(*union)
Beispiel #15
0
    def render(self, renderer):
        renderer.table_header([
            ("User", "user", "15"),
            ("Session", "session", "15"),
            ("Terminal vnode", "vnode", "30"),
            ("Recovered input", "input", "75"),
            ("Recovered output", "output", "75")])

        for terminal in self.session.entities.find("has component Terminal"):

            buffer_in = self.session.entities.find_first(
                expression.Intersection(
                    expression.Equivalence(
                        expression.Binding("Buffer/purpose"),
                        expression.Literal("terminal_input")),
                    expression.Equivalence(
                        expression.Binding("Buffer/context"),
                        expression.Literal(terminal.identity))))

            buffer_out = self.session.entities.find_first(
                expression.Intersection(
                    expression.Equivalence(
                        expression.Binding("Buffer/purpose"),
                        expression.Literal("terminal_output")),
                    expression.Equivalence(
                        expression.Binding("Buffer/context"),
                        expression.Literal(terminal.identity))))

            renderer.table_row(
                terminal["Terminal/session"]["Session/user"]["User/username"],
                terminal["Terminal/session"]["Session/sid"],
                terminal.get("Terminal/file", complete=True)["File/path"],
                repr(self.SHORTENER.sub("<whitespace>",
                                        buffer_in["Buffer/contents"])),
                repr(self.SHORTENER.sub("<whitespace>",
                                        buffer_out["Buffer/contents"])))
Beispiel #16
0
    def testRealExample(self):
        original = expression.Intersection(
            expression.Let(
                expression.Let(expression.Binding('MemoryDescriptor'),
                               expression.Binding('process')),
                expression.Equivalence(
                    expression.Let(expression.Binding('Process'),
                                   expression.Binding('command')),
                    expression.Literal('Adium'))),
            expression.Intersection(
                expression.Membership(
                    expression.Literal('execute'),
                    expression.Let(expression.Binding('MemoryDescriptor'),
                                   expression.Binding('permissions'))),
                expression.Membership(
                    expression.Literal('write'),
                    expression.Let(expression.Binding('MemoryDescriptor'),
                                   expression.Binding('permissions')))))

        # Two binary intersections become one variadic intersection and the
        # let-forms now have a Binding as their LHS whenever possible.
        expected = expression.Intersection(
            expression.Let(
                expression.Binding('MemoryDescriptor'),
                expression.Let(
                    expression.Binding('process'),
                    expression.Equivalence(
                        expression.Let(expression.Binding('Process'),
                                       expression.Binding('command')),
                        expression.Literal('Adium')))),
            expression.Membership(
                expression.Literal('execute'),
                expression.Let(expression.Binding('MemoryDescriptor'),
                               expression.Binding('permissions'))),
            expression.Membership(
                expression.Literal('write'),
                expression.Let(expression.Binding('MemoryDescriptor'),
                               expression.Binding('permissions'))))

        self.assertResult(original, expected)
Beispiel #17
0
def NegateValue(*args, **kwargs):
    return expression.Product(
        expression.Literal(-1),
        *args,
        **kwargs)
Beispiel #18
0
    def next_atom(self):
        token = self.tokenizer.next_token()

        if token is None:
            return self.error("Unexpected end of input.")

        if token.name == "infix":
            if token.value == "-":
                # As it turns out, minus signs can be prefix operators! Who
                # knew? Certainly not the tokenizer.
                token.name = "prefix"
            else:
                return self.error("Unexpected infix operator.", token)

        if token.name == "prefix":
            operator = PREFIX[token.value]
            lhs = self.next_atom()
            rhs = self.next_expression(lhs, operator.precedence)
            return self._handle_expr(operator, rhs, start=token.start,
                                     end=rhs.end)

        if token.name == "literal":
            return expression.Literal(token.value, start=token.start,
                                      end=token.end)

        if token.name == "param":
            return expression.Literal(self._replace_param(token),
                                      start=token.start, end=token.end)

        if token.name == "symbol":
            return expression.Binding(token.value, start=token.start,
                                      end=token.end)

        if token.name == "lparen":
            # Parentheses can denote subexpressions or lists. Lists have at
            # least one comma before rparen (just like Python).
            lhs = self.next_atom()
            expr = self.next_expression(lhs, 0)
            if self.tokenizer.current_token is None:
                return self.error("End of input before closing parenthesis.",
                                  token)

            if self.tokenizer.peek().name == "comma":
                # It's a list, not an expression. Build it out as a literal.
                if not isinstance(lhs, expression.Literal):
                    return self.error(
                        "Non-literal value in list.", lhs)

                self.tokenizer.next_token()
                vals = [lhs.value]

                while (self.tokenizer.current_token and
                       self.tokenizer.current_token.name == "comma"):
                    atom = self.next_atom()
                    if not isinstance(atom, expression.Literal):
                        return self.error(
                            "Non-literal value in list", atom)
                    vals.append(atom.value)
                    self.tokenizer.next_token()

                if (self.tokenizer.current_token is None or
                        self.tokenizer.current_token.name != "rparen"):
                    self.error("Lists must end with a closing paren.",
                               self.tokenizer.current_token)

                return expression.Literal(tuple(vals), start=token.start,
                                          end=self.tokenizer.position)

            elif self.tokenizer.peek().name != "rparen":
                # We got here because there's still some stuff left to parse
                # and the next token is not an rparen. That can mean that an
                # infix operator is missing or that the parens are unmatched.
                # Decide which is more likely and raise the appropriate error.
                lparens = 1
                rparens = 0
                lookahead = 2
                while self.tokenizer.peek(lookahead):
                    if self.tokenizer.peek(lookahead).name == "lparen":
                        lparens += 1
                    elif self.tokenizer.peek(lookahead).name == "rparen":
                        rparens += 1

                    lookahead += 1

                if lparens > rparens:
                    return self.error("Ummatched left parenthesis.", token)
                else:
                    next_token = self.tokenizer.peek()
                    return self.error(
                        "Was not expecting %s here." % next_token.value,
                        next_token)

            self.tokenizer.next_token()
            return expr

        return self.error("Cannot handle token %s." % token, token)
Beispiel #19
0
 def testEliminateEmpties(self):
     self.assertResult(expression.Intersection(expression.Literal(True)),
                       expression.Literal(True))
Beispiel #20
0
 def testEquivalence(self):
     query = "10 is 10"
     expected = expression.Equivalence(expression.Literal(10),
                                       expression.Literal(10))
     self.assertQueryMatches(query, expected)
Beispiel #21
0
 def testLiterals(self):
     query = "0xff"
     expected = expression.Literal(255)
     self.assertQueryMatches(query, expected)
Beispiel #22
0
 def testNestedParens(self):
     query = "Process/pid in ((1,2))"
     expected = expression.Membership(expression.Binding("Process/pid"),
                                      expression.Literal((1, 2)))
     self.assertQueryMatches(query, expected)