コード例 #1
0
ファイル: solve.py プロジェクト: rlugojr/dotty
    def testRepeat(self):
        query = q.Query("(1, 2, 3, 4)")
        self.assertEqual(
            solve.solve(query, {}).value, repeated.meld(1, 2, 3, 4))

        # Repeated values flatten automatically.
        query = q.Query("(1, (2, 3), 4)")
        self.assertEqual(
            solve.solve(query, {}).value, repeated.meld(1, 2, 3, 4))

        # Expressions work.
        query = q.Query("(1, (2 + 2), 3, 4)")
        self.assertEqual(
            solve.solve(query, {}).value, repeated.meld(1, 4, 3, 4))

        # Repeated values are mono-types.
        with self.assertRaises(errors.EfilterTypeError):
            query = q.Query("(1, 'foo', 3, 4)")
            solve.solve(query, {})

        # None should be skipped.
        query = q.Query(
            ast.Repeat(ast.Literal(None), ast.Literal(2), ast.Literal(None),
                       ast.Literal(4)))
        self.assertEqual(solve.solve(query, {}).value, repeated.meld(2, 4))
コード例 #2
0
 def testPrefix(self):
     self.assertQueryParses(
         "-5 + 5 eq - (10)",
         ast.Equivalence(
             ast.Sum(ast.Product(ast.Literal(-1), ast.Literal(5)),
                     ast.Literal(5)),
             ast.Product(ast.Literal(-1), ast.Literal(10))))
コード例 #3
0
 def testInfix(self):
     self.assertQueryMatches(
         "x == 'foo' and y.z contains 'bar'",
         ast.Intersection(
             ast.Equivalence(ast.Var("x"), ast.Literal("foo")),
             ast.Membership(ast.Literal("bar"),
                            ast.Resolve(ast.Var("y"), ast.Literal("z")))))
コード例 #4
0
    def _ParseTaggingFile(self, tag_file_path):
        """Parses tag definitions from the source.

    Args:
      tag_file_path (str): path to the tag file.

    Returns:
      efilter.ast.Expression: efilter abstract syntax tree (AST), containing the
          tagging rules.
    """
        tags = []
        for label_name, rules in self._ParseDefinitions(tag_file_path):
            if not rules:
                logging.warning(
                    u'All rules for label "{0:s}" are invalid.'.format(
                        label_name))
                continue

            tag = efilter_ast.IfElse(
                # Union will be true if any of the 'rules' match.
                efilter_ast.Union(*[rule.root for rule in rules]),
                # If so then evaluate to a string with the name of the tag.
                efilter_ast.Literal(label_name),
                # Otherwise don't return anything.
                efilter_ast.Literal(None))
            tags.append(tag)

        # Generate a repeated value with all the tags (None will be skipped).
        return efilter_ast.Repeat(*tags)
コード例 #5
0
ファイル: parser.py プロジェクト: rekall-innovations/efilter
    def select_what(self):
        # Each value we select is in form EXPRESSION [AS SYMBOL]. Values are
        # separated by commas.
        start = self.tokens.matched.start
        used_names = set()  # Keeps track of named values to prevent duplicates.
        vars = []
        for idx in itertools.count():
            value_expression = self.expression()

            if self.tokens.accept(grammar.select_as):
                # If there's an AS then we have an explicit name for this value.
                self.tokens.expect(common_grammar.symbol)

                if self.tokens.matched.value in used_names:
                    return self.error(
                        "Duplicate 'AS' name %r." % self.tokens.matched.value)

                key_expression = ast.Literal(self.tokens.matched.value,
                                             start=self.tokens.matched.start,
                                             end=self.tokens.matched.end,
                                             source=self.original)

                # Record the value expression of the alias.
                self.aliases[-1][self.tokens.matched.value] = value_expression

                used_names.add(self.tokens.matched.value)
            else:
                # Try to guess the appropriate name of the column based on what
                # the expression is.
                name = self._guess_name_of(value_expression)

                if (not name or
                        name in used_names or
                        (self.scope and name in self.scope)):
                    # Give up and just use the current idx for key.
                    name = "column_%d" % (idx,)
                else:
                    used_names.add(name)

                key_expression = ast.Literal(name)

            end = key_expression.end or value_expression.end
            vars.append(ast.Pair(key_expression, value_expression,
                                 start=value_expression.start, end=end,
                                 source=self.original))

            if self.tokens.accept(grammar.select_from):
                # Make ast.Bind here.
                source_expression = self.select_from()
                return ast.Map(
                    source_expression,
                    ast.Bind(*vars, start=start, end=vars[-1].end,
                             source=self.original),
                    start=start,
                    end=self.tokens.matched.end,
                    source=self.original)

            self.tokens.expect(common_grammar.comma)
コード例 #6
0
    def testIfElse(self):
        # Missing else:
        q = query.Query(
            ast.IfElse(
                ast.Pair(ast.Literal(True), ast.Literal("foo")),
                ast.Pair(ast.Literal(True), ast.Literal("bar"))))

        with self.assertRaises(errors.EfilterLogicError):
            validate.validate(q)
コード例 #7
0
    def testSelectLimit(self):
        self.assertQueryMatches(
            "SELECT * FROM pslist LIMIT 10",
            ast.Apply(ast.Var("take"), ast.Literal(10), ast.Var("pslist")))

        self.assertQueryMatches(
            "SELECT * FROM pslist LIMIT 10 OFFSET 5",
            ast.Apply(
                ast.Var("take"), ast.Literal(10),
                ast.Apply(ast.Var("drop"), ast.Literal(5), ast.Var("pslist"))))
コード例 #8
0
    def testComplexSelect(self):
        query = ("(SELECT proc.parent.pid AS ppid, proc.pid FROM pslist(10) "
                 "WHERE COUNT(proc.open_files) > 10) and True")

        expected = ast.Intersection(
            ast.Map(
                ast.Filter(
                    ast.Apply(ast.Var("pslist"), ast.Literal(10)),
                    ast.StrictOrderedSet(
                        ast.Apply(
                            ast.Var("COUNT"),
                            ast.Resolve(ast.Var("proc"),
                                        ast.Literal("open_files"))),
                        ast.Literal(10))),
                ast.Bind(
                    ast.Pair(
                        ast.Literal("ppid"),
                        ast.Resolve(
                            ast.Resolve(ast.Var("proc"),
                                        ast.Literal("parent")),
                            ast.Literal("pid"))),
                    ast.Pair(ast.Literal("pid"),
                             ast.Resolve(ast.Var("proc"),
                                         ast.Literal("pid"))))),
            ast.Literal(True))

        self.assertQueryMatches(query, expected)
コード例 #9
0
    def testListLiterals(self):
        self.assertQueryMatches(
            "[1, 2, 3]",
            ast.Tuple(ast.Literal(1), ast.Literal(2), ast.Literal(3)))

        # Empty list literals should work.
        self.assertQueryMatches("[]", ast.Tuple())

        # Arbitrary AST should now be allowed in lists.
        self.assertQueryMatches(
            "[x, f(x)]",
            ast.Tuple(ast.Var("x"), ast.Apply(ast.Var("f"), ast.Var("x"))))
コード例 #10
0
    def testLiterals(self):
        # Numbers:
        self.assertQueryMatches("5", ast.Literal(5))
        self.assertQueryRaises("5)")

        # Strings:
        self.assertQueryMatches("'foo'", ast.Literal("foo"))

        # Booleans:
        self.assertQueryMatches("true", ast.Literal(True))
        self.assertQueryMatches("false", ast.Literal(False))
        self.assertQueryMatches("TRUE", ast.Literal(True))
        self.assertQueryMatches("TRU", ast.Var("TRU"))
コード例 #11
0
ファイル: tag.py プロジェクト: rlugojr/dotty
    def parse(self):
        tags = []
        for tag_name, rules in self._parse_tagfile():
            tag = ast.IfElse(
                # Union will be true if any of the 'rules' match.
                ast.Union(*[rule.root for rule in rules]),
                # If so then evaluate to a string with the name of the tag.
                ast.Literal(tag_name),
                # Otherwise don't return anything.
                ast.Literal(None))
            tags.append(tag)

        self.original.close()
        # Generate a repeated value with all the tags (None will be skipped).
        return ast.Repeat(*tags)
コード例 #12
0
ファイル: parser.py プロジェクト: rekall-innovations/efilter
    def let(self):
        saved_start = self.tokens.matched.start

        expect_rparens = 0
        while self.tokens.accept(common_grammar.lparen):
            expect_rparens += 1

        bindings = []
        while True:
            symbol = self.tokens.expect(common_grammar.symbol)
            binding = ast.Literal(symbol.value, start=symbol.start,
                                  end=symbol.end, source=self.original)

            self.tokens.expect(grammar.let_assign)

            value = self.expression()
            bindings.append(ast.Pair(binding, value, start=binding.start,
                                     end=value.end, source=self.original))

            if not self.tokens.accept(common_grammar.comma):
                break

        bind = ast.Bind(*bindings, start=bindings[0].start,
                        end=bindings[-1].end, source=self.original)

        while expect_rparens:
            self.tokens.expect(common_grammar.rparen)
            expect_rparens -= 1

        nested_expression = self.expression()
        return ast.Let(bind, nested_expression, start=saved_start,
                       end=nested_expression.end, source=self.original)
コード例 #13
0
 def testFormatters(self):
     """Creating a query with raw AST should generate the source."""
     q = query.Query(
         ast.Complement(
             ast.Equivalence(ast.Map(ast.Var("Process"), ast.Var("pid")),
                             ast.Literal(10))))
     self.assertEqual(q.source, "Process.pid != 10")
コード例 #14
0
def NormalizeResolve(x, y, **kwargs):
    if isinstance(y, ast.Var):
        literal_y = ast.Literal(y.value, start=y.start, end=y.end,
                                source=y.source)
    else:
        raise TypeError("Type of RHS must be Var. Got %r." % y)

    return ast.Resolve(x, literal_y, **kwargs)
コード例 #15
0
    def testInfix(self):
        self.assertQueryMatches("x + y", ast.Sum(ast.Var("x"), ast.Var("y")))

        self.assertQueryMatches(
            "w.x.y.z",
            ast.Resolve(
                ast.Resolve(ast.Resolve(ast.Var("w"), ast.Literal("x")),
                            ast.Literal("y")), ast.Literal("z")))

        # Operator precedence should work correctly.
        self.assertQueryMatches(
            "x + y * z",
            ast.Sum(ast.Var("x"), ast.Product(ast.Var("y"), ast.Var("z"))))

        self.assertQueryMatches(
            "x * y + z",
            ast.Sum(ast.Product(ast.Var("x"), ast.Var("y")), ast.Var("z")))
コード例 #16
0
ファイル: parser.py プロジェクト: rekall-innovations/efilter
    def dot_rhs(self):
        """Match the right-hand side of a dot (.) operator.

        The RHS must be a symbol token, but it is interpreted as a literal
        string (because that's what goes in the AST of Resolve.)
        """
        self.tokens.expect(common_grammar.symbol)
        return ast.Literal(self.tokens.matched.value,
                           start=self.tokens.matched.start,
                           end=self.tokens.matched.end, source=self.original)
コード例 #17
0
 def testSelectWhereOrder(self):
     self.assertQueryMatches(
         "SELECT * FROM pslist() WHERE pid == 1 ORDER BY command DESC",
         ast.Apply(
             ast.Var("reverse"),
             ast.Sort(
                 ast.Filter(ast.Apply(ast.Var("pslist")),
                            ast.Equivalence(ast.Var("pid"),
                                            ast.Literal(1))),
                 ast.Var("command"))))
コード例 #18
0
    def testMixfix(self):
        self.assertQueryParses("'foo'[0  ]",
                               ast.Select(ast.Literal("foo"), ast.Literal(0)))

        self.assertQueryParses(
            # I refer you to my previous statement about making sense.
            " (5 +5) [ 'foo']",
            ast.Select(ast.Sum(ast.Literal(5), ast.Literal(5)),
                       ast.Literal("foo")))

        self.assertQueryParses(
            "5 + 5['foo' + 10]",
            ast.Sum(
                ast.Literal(5),
                ast.Select(ast.Literal(5),
                           ast.Sum(ast.Literal("foo"), ast.Literal(10)))))
コード例 #19
0
    def testOperatorPrecedence(self):
        # Prefix operator, like the unary minus sign, should respect operator
        # precedence order.
        self.assertQueryMatches(
            "-x + y",
            ast.Sum(ast.Product(ast.Literal(-1), ast.Var("x")), ast.Var("y")))

        self.assertQueryMatches(
            "not x and y",
            ast.Intersection(ast.Complement(ast.Var("x")), ast.Var("y")))

        self.assertQueryMatches(
            "x / -f(y) or not z(a, b)",
            ast.Union(
                ast.Quotient(
                    ast.Var("x"),
                    ast.Product(ast.Literal(-1),
                                ast.Apply(ast.Var("f"), ast.Var("y")))),
                ast.Complement(
                    ast.Apply(ast.Var("z"), ast.Var("a"), ast.Var("b")))))
コード例 #20
0
ファイル: solve.py プロジェクト: rekall-innovations/efilter
    def testRepeat(self):
        query = q.Query("(1, 2, 3, 4)")
        self.assertEqual(
            solve.solve(query, {}).value, repeated.meld(1, 2, 3, 4))

        # Repeated values do not flatten automatically.
        query = q.Query("(1, (2, 3), 4)")
        self.assertEqual(
            solve.solve(query, {}).value, repeated.meld(1, [2, 3], 4))

        # Expressions work.
        query = q.Query("(1, (2 + 2), 3, 4)")
        self.assertEqual(
            solve.solve(query, {}).value,
            # Operators always return a list.
            repeated.meld(1, [4], 3, 4))

        # None should be skipped.
        query = q.Query(
            ast.Repeat(ast.Literal(None), ast.Literal(2), ast.Literal(None),
                       ast.Literal(4)))
        self.assertEqual(solve.solve(query, {}).value, repeated.meld(2, 4))
コード例 #21
0
ファイル: lisp.py プロジェクト: rlugojr/dotty
    def _parse_s_expression(self, atom):
        car = atom[0]
        cdr = atom[1:]

        # Vars are a little special. Don't make the value a Literal.
        if car == "var":
            return ast.Var(cdr[0])

        # Params are interpolated right away.
        if car == "param":
            return ast.Literal(self.params[cdr[0]])

        return EXPRESSIONS[car](*[self._parse_atom(a) for a in cdr])
コード例 #22
0
ファイル: asdottysql.py プロジェクト: rlugojr/dotty
def asdottysql(expr):
    branches = [
        "if %s then %s" % (asdottysql(c), asdottysql(v))
        for c, v in expr.conditions()
    ]

    if_ = " else ".join(branches)

    else_ = expr.default()
    if not else_ or else_ == ast.Literal(None):
        return if_

    return "%s else %s" % (if_, asdottysql(else_))
コード例 #23
0
    def testCircumfix(self):
        self.assertQueryParses(
            "[1, 2, 3]",
            ast.Tuple(ast.Literal(1), ast.Literal(2), ast.Literal(3)))

        self.assertQueryParses(
            # Lists and selection are non-ambiguous.
            "10 + ['foo', 'bar'][1]",
            ast.Sum(
                ast.Literal(10),
                ast.Select(ast.Tuple(ast.Literal("foo"), ast.Literal("bar")),
                           ast.Literal(1))))
コード例 #24
0
    def testLet(self):
        self.assertQueryMatches(
            "let x = 5, y = 10 x + y",
            ast.Let(
                ast.Bind(ast.Pair(ast.Literal("x"), ast.Literal(5)),
                         ast.Pair(ast.Literal("y"), ast.Literal(10))),
                ast.Sum(ast.Var("x"), ast.Var("y"))))

        self.assertQueryMatches(
            "let( (x = 5 - 3,y=(10+(10)) ) )x + y",
            ast.Let(
                ast.Bind(
                    ast.Pair(ast.Literal("x"),
                             ast.Difference(ast.Literal(5), ast.Literal(3))),
                    ast.Pair(ast.Literal("y"),
                             ast.Sum(ast.Literal(10), ast.Literal(10)))),
                ast.Sum(ast.Var("x"), ast.Var("y"))))

        self.assertQueryRaises("let x = 5) x + 5")
        self.assertQueryRaises("let ((x = 5) x + 5")
        self.assertQueryRaises("let (x = 5)) x + 5")
        self.assertQueryRaises("let (x = 5 x + 5")
        self.assertQueryRaises("let (x = 5)")
コード例 #25
0
    def GetEventTaggingRules(self):
        """Retrieves the event tagging rules from the tagging file.

    Returns:
      efilter.ast.Expression: efilter abstract syntax tree (AST), containing the
          tagging rules.
    """
        tags = []
        for label_name, rules in self._ParseDefinitions(self._path):
            if not rules:
                continue

            tag = efilter_ast.IfElse(
                # Union will be true if any of the 'rules' match.
                efilter_ast.Union(*[rule.root for rule in rules]),
                # If so then evaluate to a string with the name of the tag.
                efilter_ast.Literal(label_name),
                # Otherwise don't return anything.
                efilter_ast.Literal(None))
            tags.append(tag)

        # Generate a repeated value with all the tags (None will be skipped).
        return efilter_ast.Repeat(*tags)
コード例 #26
0
ファイル: parser.py プロジェクト: rlugojr/dotty
    def atom(self):
        # Unary operator.
        if self.tokens.accept(grammar.prefix, self.operators):
            operator = self.tokens.matched.operator
            start = self.tokens.matched.start
            children = [self.expression(operator.precedence)]

            # Allow infix to be repeated in circumfix operators.
            if operator.infix:
                while self.tokens.accept(grammar.match_tokens(operator.infix)):
                    children.append(self.expression())

            # If we have a suffix expect it now.
            if operator.suffix:
                self.tokens.expect(grammar.match_tokens(operator.suffix))

            return operator.handler(*children,
                                    start=start,
                                    end=self.tokens.matched.end,
                                    source=self.original)

        if self.tokens.accept(grammar.literal):
            return ast.Literal(self.tokens.matched.value,
                               source=self.original,
                               start=self.tokens.matched.start,
                               end=self.tokens.matched.end)

        if self.tokens.accept(grammar.symbol):
            return ast.Var(self.tokens.matched.value,
                           source=self.original,
                           start=self.tokens.matched.start,
                           end=self.tokens.matched.end)

        if self.tokens.accept(grammar.lparen):
            expr = self.expression()
            self.tokens.expect(grammar.rparen)
            return expr

        if self.tokens.peek(0):
            raise errors.EfilterParseError(
                message="Was not expecting %r here." %
                self.tokens.peek(0).name,
                token=self.tokens.peek(0))
        else:
            raise errors.EfilterParseError("Unexpected end of input.")
コード例 #27
0
ファイル: parser.py プロジェクト: rekall-innovations/efilter
    def param(self):
        if self.tokens.matched.value is None:
            param = self.last_param
            self.last_param += 1
        elif isinstance(self.tokens.matched.value, int):
            param = self.last_param = self.tokens.matched.value
        elif isinstance(self.tokens.matched.value, six.string_types):
            param = self.tokens.matched.value
        else:
            return self.error(
                "Invalid param %r." % self.tokens.matched.value,
                start_token=self.tokens.matched.first)

        if param not in self.params:
            return self.error(
                "Param %r unavailable. (Available: %r)" % (param, self.params),
                start_token=self.tokens.matched.first)

        return ast.Literal(self.params[param], start=self.tokens.matched.start,
                           end=self.tokens.matched.end, source=self.original)
コード例 #28
0
ファイル: solve.py プロジェクト: rekall-innovations/efilter
    def testLet(self):
        self.assertEqual(
            solve.solve(
                ast.Let(ast.Bind(ast.Pair(ast.Literal("x"), ast.Literal(5))),
                        ast.Sum(ast.Var("x"), ast.Var("x"))), {}).value, [10])

        # Previous binding should be made available to subsequent bindings.
        self.assertEqual(
            solve.solve(
                ast.Let(
                    ast.Bind(
                        ast.Pair(ast.Literal("x"), ast.Literal(5)),
                        ast.Pair(ast.Literal("y"),
                                 ast.Sum(ast.Var("x"), ast.Literal(5)))),
                    ast.Var("y")), {}).value, [10])
コード例 #29
0
    def testKVPairs(self):
        self.assertQueryMatches("x: y", ast.Pair(ast.Var("x"), ast.Var("y")))

        # KV pairs are used in named function arguments:
        self.assertQueryMatches(
            "f(10, 'strings': ['foo', 'bar'])",
            ast.Apply(
                ast.Var("f"), ast.Literal(10),
                ast.Pair(ast.Literal("strings"),
                         ast.Tuple(ast.Literal("foo"), ast.Literal("bar")))))

        # They can also appear in repeated values, forming a logical dictionary:
        self.assertQueryMatches(
            "('foo': foo, 'bar': bar)",
            ast.Repeat(ast.Pair(ast.Literal("foo"), ast.Var("foo")),
                       ast.Pair(ast.Literal("bar"), ast.Var("bar"))))
コード例 #30
0
ファイル: parser.py プロジェクト: rekall-innovations/efilter
    def if_if(self):
        start = self.tokens.matched.start

        # Even-numbered children are conditions; odd-numbered are results.
        # Last child is the else expression.
        children = [self.expression()]

        self.tokens.expect(grammar.if_then)
        children.append(self.expression())

        while self.tokens.accept(grammar.if_else_if):
            children.append(self.expression())
            self.tokens.expect(grammar.if_then)
            children.append(self.expression())

        if self.tokens.accept(grammar.if_else):
            children.append(self.expression())
        else:
            children.append(ast.Literal(None))

        return ast.IfElse(*children, start=start, end=self.tokens.matched.end,
                          source=self.original)