Beispiel #1
0
def make_klee_symbolic(variable_name, trackingName):
    arg1 = c_ast.UnaryOp(op='&', expr=c_ast.ID(variable_name))
    arg2 = c_ast.UnaryOp(op='sizeof', expr = c_ast.Typename(name=None, quals =[],
                                                            type= c_ast.TypeDecl(declname=None,quals=[],
                                                                                 type=c_ast.IdentifierType(names=['int']))))
    arg3 = c_ast.Constant(type='string', value='\"'+ trackingName +'\"')
    return c_ast.FuncCall(name=c_ast.ID(name = "klee_make_symbolic"), args=c_ast.ExprList(exprs=[arg1,arg2,arg3]))
Beispiel #2
0
    def add_to_expression(self,
                          expression: c_ast.Node,
                          operator: str,
                          addition: c_ast.ExprList = None):
        """
		Adds the additional expression to the given expression, concatenated with the given operator. If the additional
		expression is None, the operator is assumed to be unary.
		:param expression: The expression to add to.
		:param operator: An operator on expression, e.g. "&&" or "!".
		:param addition: The expression to add.
		:return: The merged expression.
		:rtype: c_ast.ExprList
		"""
        expressions = []
        if type(expression) is c_ast.ExprList:
            for expr in expression.exprs:
                if addition is None:
                    expressions.append(
                        c_ast.UnaryOp(operator, copy.deepcopy(expr)))
                else:
                    expressions.append(
                        c_ast.BinaryOp(operator, copy.deepcopy(expr),
                                       addition))
        else:
            if addition is None:
                expressions.append(
                    c_ast.UnaryOp(operator, copy.deepcopy(expression)))
            else:
                expressions.append(
                    c_ast.BinaryOp(operator, copy.deepcopy(expression),
                                   addition))
        return c_ast.ExprList(expressions)
def perm_refer_to_var(fn: ca.FuncDef, ast: ca.FileAST, indices: Indices,
                      region: Region, random: Random) -> bool:
    """Add `if (variable) {}` or `if (struct.member) {}` in a random place.
    This will get optimized away but may affect regalloc."""
    # Find expression to insert, searching within the randomization region.
    cands: List[Expression] = [
        expr for expr in get_block_expressions(fn.body, region)
        if isinstance(expr, (ca.StructRef, ca.ID))
    ]
    if not cands:
        return False
    expr = random.choice(cands)
    if ast_util.is_effectful(expr):
        return False
    type: SimpleType = decayed_expr_type(expr, build_typemap(ast))
    if isinstance(type, ca.TypeDecl) and isinstance(type.type,
                                                    (ca.Struct, ca.Union)):
        expr = ca.UnaryOp("&", expr)

    if random.choice([True, False]):
        expr = ca.UnaryOp("!", expr)

    # Insert it wherever -- possibly outside the randomization region, since regalloc
    # can act at a distance. (Except before a declaration.)
    ins_cands = get_insertion_points(fn, Region.unbounded())
    ins_cands = [c for c in ins_cands if not isinstance(c[2], ca.Decl)]
    if not ins_cands:
        return False

    cond = copy.deepcopy(expr)
    stmt = ca.If(cond=cond, iftrue=ca.Compound(block_items=[]), iffalse=None)
    tob, toi, _ = random.choice(ins_cands)
    ast_util.insert_statement(tob, toi, stmt)
    return True
Beispiel #4
0
def rename_array_args(funcdef):
    """
  Rename and copy arrays passed as arguments to funcdef.
  """
    # For each argument
    for param in funcdef.decl.type.args.params:
        if isinstance(param.type, c_ast.ArrayDecl):
            # Rename and copy array
            arg_decl = copy.deepcopy(param)
            # Rename array
            v = inline.RenameVisitor()
            v.new_visit(get_decl_name(param),
                        get_decl_name(param) + "_rename", funcdef.body)
            # Add copy and declarations
            funcdef.body.block_items = rename_array_decl(
                arg_decl) + funcdef.body.block_items
        elif isinstance(param.type, c_ast.TypeDecl):
            # Simple variable passing, don't need to handle
            pass
        elif isinstance(param.type, c_ast.PtrDecl):
            # Don't copy pointer arguments
            return
            """
      Param of form: type *var
      is copied in the function body using:
        type var_rename _temp = *var;
        type *var_rename = &var_rename_temp;
      """
            # General pointer arguments
            old_name = get_decl_name(param)
            new_name = old_name + "_rename"
            temp_name = new_name + "_temp"
            # Rename variable use in function body
            v = inline.RenameVisitor()
            v.new_visit(old_name, new_name, funcdef.body)

            # type var_rename_temp = *var;
            decl1 = c_ast.Decl(
                temp_name, None, None, None,
                c_ast.TypeDecl(temp_name, None, param.type.type.type),
                c_ast.UnaryOp('*', c_ast.ID(old_name)), None)

            # type *var_rename = &var_rename_temp;
            decl2 = c_ast.Decl(
                new_name, None, None, None,
                c_ast.PtrDecl([],
                              c_ast.TypeDecl(new_name, None,
                                             param.type.type.type)),
                c_ast.UnaryOp('&', c_ast.ID(temp_name)), None)

            # Insert into function body
            funcdef.body.block_items.insert(0, decl2)
            funcdef.body.block_items.insert(0, decl1)
        else:
            print_node(param)
            param.show(nodenames=True, showcoord=True)
            raise Exception(
                "Unhandled argument type %s. Implement or verify that it can be ignored."
                % (type(param.type)))
Beispiel #5
0
def _generate_write(name, address=True):
    """ Helper function generate write functions

    """
    if address:
        target = c_ast.UnaryOp('&', c_ast.ID(name))
    else:
        target = c_ast.ID(name)
    return c_ast.FuncCall(
        c_ast.ID('_rpc_write'),
        c_ast.ExprList([target,
                        c_ast.UnaryOp('sizeof', c_ast.ID(name))]))
Beispiel #6
0
def _generate_read(name, size=None, address=True):
    """ Helper function to generate read functions. size
    should be an AST fragment

    """
    if size is None:
        size = c_ast.UnaryOp('sizeof', c_ast.ID(name))
    if address:
        target = c_ast.UnaryOp('&', c_ast.ID(name))
    else:
        target = c_ast.ID(name)

    return c_ast.FuncCall(c_ast.ID('_rpc_read'), c_ast.ExprList([target,
                                                                 size]))
Beispiel #7
0
def nested_for_loop(node, inner_loop_body, loop_iterator_base, rename_index=0):
    """
  Recursively create nested for loops for copying a multi-dimensional array.
  """
    if isinstance(node.type.type, c_ast.ArrayDecl):
        # Multi-dimensional array, recurse to generate inner loop
        for_loop_body = nested_for_loop(node.type, inner_loop_body,
                                        loop_iterator_base, rename_index + 1)
    else:
        # Single or last dimension of array
        for_loop_body = [inner_loop_body]

    # Declare iterator
    loop_iterator = c_ast.ID("%s_i%d" % (loop_iterator_base, rename_index))
    loop_iterator_decl = c_ast.Decl(
        loop_iterator.name, [], [], [],
        c_ast.TypeDecl(loop_iterator.name, [], c_ast.IdentifierType(["int"])),
        None, None)
    # For loop
    array_size = node.type.dim
    for_loop = c_ast.For(
        c_ast.Assignment('=', loop_iterator, c_ast.Constant("int", "0")),
        c_ast.BinaryOp('<', loop_iterator, array_size),
        c_ast.UnaryOp('p++', loop_iterator), c_ast.Compound(for_loop_body))
    return [loop_iterator_decl, for_loop]
 def replacer(e: Expression) -> Optional[Expression]:
     if e in replace_cand_set:
         if should_make_ptr:
             return ca.UnaryOp("*", ca.ID(var))
         else:
             return ca.ID(var)
     return None
Beispiel #9
0
def check_value(ast_tree, ext_index, bock_item_index, var_name, func_name):
    Cast = c_ast.Cast(
        c_ast.Typename(
            None, [],
            c_ast.PtrDecl([],
                          c_ast.TypeDecl(None, [],
                                         c_ast.IdentifierType(['void'])))),
        c_ast.ID(var_name))

    func_call = c_ast.FuncCall(
        c_ast.ID('check_value'),
        c_ast.ExprList([
            c_ast.UnaryOp('&', c_ast.ID('global_log')), Cast,
            c_ast.Constant('string', '"' + var_name + '"'),
            c_ast.Constant('string', '"' + func_name + '"'),
            c_ast.Constant('int', str(len(var_name))),
            c_ast.Constant('int', str(len(func_name)))
        ]))

    new_node = c_ast.If(
        c_ast.BinaryOp('==', func_call, c_ast.Constant('int', '0')),
        c_ast.Compound([
            c_ast.FuncCall(
                c_ast.ID('printf'),
                c_ast.ExprList([
                    c_ast.Constant('string', '"%s\\n"'),
                    c_ast.Constant('string', '"Attack Detected"')
                ])),
            c_ast.FuncCall(c_ast.ID('exit'),
                           c_ast.ExprList([c_ast.Constant('int', '1')]))
        ]), None)
    return merge_ast_tree(ast_tree, ext_index, bock_item_index, new_node,
                          "insert_before")
Beispiel #10
0
def ConvertArrayIndexToPointerDereference(ast, meta_info):
    """
    Eliminates multi-dimensional arrays

    Phase 1:  a[1][2] = b; -> *(a + 1 * 10 + 2) = b;

    Phase 2: fun (int a[5][10]) -> fun (int a[][10])

    Phase 3:  int a[5][10]; -> int a[50];
    """

    def IsArrayRefChainHead(node, parent):
        if not isinstance(node, c_ast.ArrayRef): return False
        name_type = meta_info.type_links[node.name]
        #  int **b = a;
        #  printf("%d\n", b[1][1]);
        if not isinstance(name_type, c_ast.ArrayDecl): return True
        if not isinstance(parent, c_ast.ArrayRef): return True
        return False

    ref_chains = common.FindMatchingNodesPostOrder(ast, ast, IsArrayRefChainHead)
    for chain_head, parent in ref_chains:
        name, s = MakeCombinedSubscript(chain_head, meta_info)
        if s is None:
            addr = name
        else:
            addr = c_ast.BinaryOp("+", name, s)
        head_type = meta_info.type_links[chain_head]
        # TODO:  low confidence - double check this
        meta_info.type_links[addr] = meta_info.type_links[name]
        if isinstance(head_type, c_ast.ArrayDecl):
            # the array ref sequence only partially indexes the array, so the result is just an address
            common.ReplaceNode(parent, chain_head, addr)
        else:
            deref = c_ast.UnaryOp("*", addr)
            meta_info.type_links[deref] = meta_info.type_links[chain_head]  # expression has not changed
            common.ReplaceNode(parent, chain_head, deref)

    # Phase 2
    def IsArrayDeclParam(node, parent):
        if not isinstance(parent, c_ast.ParamList): return False
        if isinstance(node, c_ast.EllipsisParam): return False
        return isinstance(node.type, c_ast.ArrayDecl)

    decl_params = common.FindMatchingNodesPreOrder(
        ast, ast, IsArrayDeclParam)
    for param, _ in decl_params:
        t = param.type
        t.dim = None

    # Phase 3
    def IsArrayDeclChainHead(node, parent):
        if not isinstance(node, c_ast.ArrayDecl): return False
        return not isinstance(parent, c_ast.ArrayDecl)

    decl_chains = common.FindMatchingNodesPreOrder(
        ast, ast, IsArrayDeclChainHead)
    for chain_head, parent in decl_chains:
        CollapseArrayDeclChain(chain_head)
Beispiel #11
0
def ConvertArrayStructRef(ast: c_ast.FileAST):
    def IsArrowStructRef(node, _):
        return isinstance(node, c_ast.StructRef) and node.type == "->"

    candidates = common.FindMatchingNodesPostOrder(ast, ast, IsArrowStructRef)
    for struct_ref, parent in candidates:
        struct_ref.type = "."
        struct_ref.name = c_ast.UnaryOp("*", struct_ref.name)
Beispiel #12
0
def astAssiDef(isr):
    larr = c_ast.ArrayRef(
        c_ast.ID('deferral'), c_ast.Constant(
            'int',
            str(int(isr) - 1)))  # the second param of Constant is String
    rarr = c_ast.UnaryOp('&', c_ast.ID('deferral_' + isr))
    assi = c_ast.Assignment('=', larr, rarr)
    return assi
Beispiel #13
0
 def replace_underlying_sizeof(self, ut):
     for node in self.get_nodes(self.ast):
         if type(node) == c_ast.Decl:
             try:
                 if node.init.name.name == "fffc_get_sizeof_type":
                     node.init = get_sizeof_pointer_to_type(
                         ut, c_ast.UnaryOp("*", c_ast.ID("storage")))
             except AttributeError:
                 pass
Beispiel #14
0
def set_outdated(ast_tree, ext_index, bock_item_index, func_name):
    new_node = c_ast.FuncCall(
        c_ast.ID('set_outdated'),
        c_ast.ExprList([
            c_ast.UnaryOp('&', c_ast.ID('global_log')),
            c_ast.Constant('string', '"' + func_name + '"'),
            c_ast.Constant('int', str(len(func_name)))
        ]))
    return merge_ast_tree(ast_tree, ext_index, bock_item_index, new_node,
                          "insert_before")
  def visit_FuncDef(self, node):
    # Skip if no loop counters exist
    if self.loop_counter_size == 0:
      return

    # Create loop_counter declaration/initialization
    constants = [c_ast.Constant("int", '0') for i in range(self.loop_counter_size)]
    init_list = c_ast.InitList(constants)
    identifier_type = c_ast.IdentifierType(["int"])
    type_decl = c_ast.TypeDecl("loop_counter", [], identifier_type)
    dim = c_ast.Constant("int", str(self.loop_counter_size))
    array_decl = c_ast.ArrayDecl(type_decl, dim, [])
    decl = c_ast.Decl("loop_counter", [], [], [], array_decl, init_list, None) 
    node.body.block_items.insert(0, decl)

    # Label for return values to goto
    start_label = c_ast.Label("print_loop_counter", c_ast.EmptyStatement())
    # Start and end labels used for inserting preprocessor commands for #if DEBUG_EN
    end_label = c_ast.Label("print_loop_counter_end", c_ast.EmptyStatement())

    # Write to file
    if self.write_to_file:
      stmt = c_ast.ID("write_array(loop_counter, %d)\n" % (self.loop_counter_size))
      compound = c_ast.Compound([start_label, stmt, end_label])
    # Print to stdout
    else:
      # Add printf to the end of function
      # Start of printing
      stmt_start = c_ast.ID("printf(\"loop counter = (\")")

      # For loop
      # int i;
      identifier_type = c_ast.IdentifierType(["int"])
      type_decl = c_ast.TypeDecl("i", [], identifier_type)
      for_decl = c_ast.Decl("i", [], [], [], type_decl, [], None)
      # i = 0
      init = c_ast.Assignment("=", c_ast.ID("i"), c_ast.Constant("int", '0'))
      # i < self.loop_counter_size
      cond = c_ast.BinaryOp("<", c_ast.ID("i"), c_ast.Constant("int", str(self.loop_counter_size)))
      # i++
      next_stmt = c_ast.UnaryOp("p++", c_ast.ID("i"))
      # printf in for
      stmt = c_ast.ID("printf(\"%d, \", loop_counter[i])")
      # Cosntruct for loop
      stmt_for = c_ast.For(init, cond, next_stmt, stmt)

      # End of printing
      stmt_end = c_ast.ID("printf(\")\\n\")")
      
      # Put it all together
      body = c_ast.Compound([stmt_start, for_decl, stmt_for, stmt_end])
      # Surround with labels
      compound = c_ast.Compound([start_label, body, end_label])
    node.body.block_items.append(compound)
Beispiel #16
0
def papi_instr() -> Tuple[List[c_ast.Node], List[c_ast.Node]]:
    """
    :return: c_ast nodes representing the following code:
        exec(PAPI_start(set));
        *begin = clock();
        ...
        *end = clock();
        exec(PAPI_stop(set, values));
    """
    papi_start = c_ast.FuncCall(c_ast.ID('PAPI_start'), c_ast.ParamList([c_ast.ID('set')]))
    papi_stop = c_ast.FuncCall(c_ast.ID('PAPI_stop'),
                               c_ast.ParamList([c_ast.ID('set'), c_ast.ID('values')]))
    exec_start = c_ast.FuncCall(c_ast.ID('exec'), c_ast.ParamList([papi_start]))
    exec_stop = c_ast.FuncCall(c_ast.ID('exec'), c_ast.ParamList([papi_stop]))

    clock = c_ast.FuncCall(c_ast.ID('clock'), c_ast.ParamList([]))
    begin_clock = c_ast.Assignment('=', c_ast.UnaryOp('*', c_ast.ID('begin')), clock)
    end_clock = c_ast.Assignment('=', c_ast.UnaryOp('*', c_ast.ID('end')), clock)

    return [exec_start, begin_clock], [end_clock, exec_stop]
Beispiel #17
0
def assign_results(outargs, code):
    ptroutargs = [deepcopy(arg) for arg in outargs]
    rename = RenameVisitor("out")
    for arg in ptroutargs:
        rename.visit(arg)
        arg.type = c_ast.PtrDecl([], arg.type)
        arg.init = None

    for ptr, var in zip(ptroutargs, outargs):
        code.append(
            c_ast.Assignment('=', c_ast.UnaryOp('*', c_ast.ID(ptr.name)),
                             c_ast.ID(var.name)))
Beispiel #18
0
def define_sizeof_type_from_ast(argument_ast):
    prefix = "fffc_get_sizeof_"
    desired_name = CGenerator().visit(argument_ast)
    suffix = encode_hash(desired_name)
    function_name = prefix + suffix
    storage_tdecl = c_ast.Decl("storage", [], [], [],
                               c_ast.PtrDecl([], argument_ast), None, None)
    func_tdecl = c_ast.TypeDecl(
        function_name, [], c_ast.IdentifierType(["long", "long", "unsigned"]))
    funcdecl = c_ast.FuncDecl(c_ast.ParamList([storage_tdecl]), func_tdecl)
    funcdef = c_ast.FuncDef(
        c_ast.Decl(function_name, [], [], [], funcdecl, None, None),
        None,
        c_ast.Compound([
            c_ast.Return(
                c_ast.UnaryOp("sizeof", c_ast.UnaryOp("*",
                                                      c_ast.ID("storage"))))
        ]),
    )
    comment = "/* " + desired_name + "*/\n"
    kr_funcdecl = c_ast.FuncDecl(c_ast.ParamList([]), func_tdecl)
    return comment, kr_funcdecl, funcdef
Beispiel #19
0
def ConvertConvertAddressTakenScalarsToArray(ast, meta_info: meta.MetaInfo):
    """
    Rewrite address taken scalar vars as one element arrays

    After this transform we can keep all scalars in registers.
    """

    def IsAddressTakenScalarOrGlobalScalar(node, parent):
        if isinstance(node, c_ast.Decl) and IsScalarType(node.type):
            # return isinstance(parent, c_ast.FileAST)
            return (isinstance(parent, c_ast.FileAST) or
                    "static" in node.storage)

        if not isinstance(node, c_ast.UnaryOp): return False
        if node.op != "&": return False
        if not isinstance(node.expr, c_ast.ID): return False
        type = meta_info.type_links[node.expr]
        return IsScalarType(type)

    candidates = common.FindMatchingNodesPreOrder(ast, ast, IsAddressTakenScalarOrGlobalScalar)
    ids = set()
    for node, _ in candidates:
        if isinstance(node, c_ast.UnaryOp):
            ids.add(meta_info.sym_links[node.expr])
        else:
            ids.add(node)
    one = c_ast.Constant("int", "1")
    meta_info.type_links[one] = meta.INT_IDENTIFIER_TYPE

    for node in ids:
        assert isinstance(node, c_ast.Decl)
        node.type = c_ast.ArrayDecl(node.type, one, [])
        if node.init:
            node.init = c_ast.InitList([node.init])

    def IsAddressTakenScalarId(node, _):
        return isinstance(node, c_ast.ID) and meta_info.sym_links[node] in ids

    candidates = common.FindMatchingNodesPreOrder(ast, ast, IsAddressTakenScalarId)

    for node, parent in candidates:
        original_type = meta_info.type_links[node]
        meta_info.type_links[node] = meta.GetTypeForDecl(meta_info.sym_links[node].type)
        array_ref = c_ast.UnaryOp("*", node)
        meta_info.type_links[array_ref] = original_type
        common.ReplaceNode(parent, node, array_ref)
Beispiel #20
0
 def instrument(self, ast, linenum):
     value = c_ast.Constant(value='0', type='int')
     typeid = c_ast.TypeDecl(declname='inst_block',
                             quals=[],
                             type=c_ast.IdentifierType(['int']))
     blockdecl = c_ast.Decl(name='inst_block',
                            quals=[],
                            storage=[],
                            funcspec=[],
                            bitsize=None,
                            init=value,
                            type=typeid)
     ast.body.block_items.insert(0, blockdecl)
     blockplus = c_ast.UnaryOp(op="p++", expr=c_ast.ID("inst_block"))
     visitor = self.ReturnLineVisitorDecls(linenum)
     visitor.generic_visit(ast)
     for element in visitor.path:
         element.block_items.insert(0, blockplus)
Beispiel #21
0
def fndecl(name, inargs, outargs, code):
    ptroutargs = [deepcopy(arg) for arg in outargs]
    rename = RenameVisitor("out")
    for arg in ptroutargs:
        rename.visit(arg)
        arg.type = c_ast.PtrDecl([], arg.type)
        arg.init = None

    fdecl = c_ast.FuncDecl(
        c_ast.ParamList(inargs + ptroutargs),
        c_ast.TypeDecl(name, [], c_ast.IdentifierType(['void'])))
    decl = c_ast.Decl(name, [], [], [], fdecl, None, None)
    assign = []
    for ptr, var in zip(ptroutargs, outargs):
        assign.append(
            c_ast.Assignment('=', c_ast.UnaryOp('*', c_ast.ID(ptr.name)),
                             c_ast.ID(var.name)))

    comp = c_ast.Compound(code + assign)
    return c_ast.FuncDef(decl, None, comp)
Beispiel #22
0
def update_value(ast_tree, ext_index, bock_item_index, var_name, func_name,
                 var_size, func_size):
    Cast = c_ast.Cast(
        c_ast.Typename(
            None, [],
            c_ast.PtrDecl([],
                          c_ast.TypeDecl(None, [],
                                         c_ast.IdentifierType(['void'])))),
        c_ast.ID(var_name))

    new_node = c_ast.FuncCall(
        c_ast.ID('update_value'),
        c_ast.ExprList([
            c_ast.UnaryOp('&', c_ast.ID('global_log')), Cast,
            c_ast.Constant('string', '"' + var_name + '"'),
            c_ast.Constant('string', '"' + func_name + '"'),
            c_ast.Constant('int', str(var_size)),
            c_ast.Constant('int', str(func_size))
        ]))

    return merge_ast_tree(ast_tree, ext_index, bock_item_index, new_node,
                          "insert_after")
Beispiel #23
0
    def _get_assume_definition(self):
        param_name = '__cond'
        int_type = a.TypeDecl(param_name, [], a.IdentifierType(['int']))
        param_list = a.ParamList(
            [a.Decl(param_name, [], [], [], int_type, None, None)])
        assume_type = a.TypeDecl('__VERIFIER_assume', [],
                                 a.IdentifierType(['void']))
        assume_func_decl = a.FuncDecl(param_list, assume_type)
        assume_decl = a.Decl('__VERIFIER_assume', list(), list(), list(),
                             assume_func_decl, None, None)

        exit_code = a.ExprList([a.Constant('int', '0')])
        true_branch = a.Compound([a.FuncCall(a.ID('exit'), exit_code)])
        false_branch = None
        if_statement = a.If(a.UnaryOp('!', a.ID(param_name)), true_branch,
                            false_branch)

        return_statement = a.Return(None)

        body_items = [if_statement, return_statement]
        assume_body = a.Compound(body_items)
        return a.FuncDef(assume_decl, None, assume_body)
            def visitor(expr: Expression) -> None:
                if DEBUG_EAGER_TYPES:
                    decayed_expr_type(expr, typemap)

                if not region.contains_node(expr):
                    return

                orig_expr = expr
                if should_make_ptr:
                    if not ast_util.is_lvalue(expr):
                        return
                    expr = ca.UnaryOp("&", expr)

                eind = einds.get(expr, 0)
                prev_write, _ = surrounding_writes(expr, orig_expr)

                for place in assignment_cands[::-1]:
                    # If expr contains an ID which is written to within
                    # [place, expr), bail out; we're trying to move the
                    # assignment too high up.
                    # TODO: also fail on moving past function calls, or
                    # possibly-aliasing writes.
                    if indices[place[2]] <= prev_write:
                        break

                    # Make far-away places less likely, and similarly for
                    # trivial expressions.
                    eind += 1
                    prob = 1 / eind
                    if isinstance(orig_expr, (ca.ID, ca.Constant)):
                        prob *= 0.15 if should_make_ptr else 0.5
                    reuse_cand = random.choice(
                        reuse_cands) if reuse_cands else None
                    candidates.append((prob, (place, expr, reuse_cand)))

                einds[expr] = eind
 def create_loop_counter_stmt(self):
   stmt = c_ast.UnaryOp("p++", c_ast.ID("loop_counter[%d]" % (self.loop_counter_index)))
   self.loop_counter_index += 1
   return stmt
Beispiel #26
0
 def v_ArrayRef(self, n, store=False):
     # A array refrence is a[x] but this is just syntax shurger for
     #*(a + x) so just do that
     add_node = c_ast.BinaryOp("+", n.name, n.subscript)
     ptr_node = c_ast.UnaryOp(op='*', expr=add_node)
     self.v_UnaryOp(ptr_node, store)
Beispiel #27
0
    def statement_rules(self, stmt, stmt_id, parent_id):
        if type(stmt) == c_ast.Compound:
            if len(stmt.block_items) == 1:
                self.statement_rules(stmt.block_items[0], stmt_id, parent_id)
            else:
                block_id = self.next_id()
                self.rule_body.append('sequenceT({0}, {1}, {2})'.format(stmt_id, parent_id, block_id))

                items_ids = [self.next_id() for s in stmt.block_items if type(s) != c_ast.Label]

                if stmt_id == RuleID.INITIAL_ID:
                    self.rule_body.append('{0} = {1}'.format(RuleID.CHILDREN_IDs, self.list_to_string(items_ids)))
                else:
                    self.rule_body.append('length({0}, {1})'.format(block_id, len(items_ids)))

                for idx in range(0, len(stmt.block_items)):
                    if type(stmt.block_items[idx]) == c_ast.Label:
                        self.parse_label(stmt.block_items[idx])
                    else:
                        self.statement_rules(stmt.block_items[idx], items_ids[idx], stmt_id)
                        if idx > 0:
                            self.rule_body.append('directly_after({0}, {1}, {2})'.format(items_ids[idx], items_ids[idx-1], block_id))

        elif type(stmt) == c_ast.While or type(stmt) == c_ast.DoWhile:
            # LoopNode(LoopType.PRE_TESTED, get_ast(stmt.stmt), get_ast(stmt.cond))
            condition_id = self.next_id()
            body_id = self.next_id()
            loop_type = 'doWhile' if type(stmt) == c_ast.DoWhile else 'while'
            self.rule_body.append('loopT({0}, {1}, \'{2}\', {3}, {4})'.format(stmt_id, parent_id, loop_type, condition_id, body_id))
            self.statement_rules(stmt.cond, condition_id, stmt_id)
            self.statement_rules(stmt.stmt, body_id, stmt_id)

        elif type(stmt) == c_ast.For:
            pass

        elif type(stmt) == c_ast.If:
            #ConditionNode(stmt.cond, stmt.iftrue, stmt.iffalse)
            condition_id = self.next_id()
            true_id = self.next_id() if stmt.iftrue is not None else '\'null\''
            false_id = self.next_id() if stmt.iffalse is not None else '\'null\''
            self.rule_body.append('ifT({0}, {1}, {2}, {3}, {4})'.format(stmt_id, parent_id, condition_id, true_id, false_id))
            self.statement_rules(stmt.cond, condition_id, stmt_id)
            if stmt.iftrue is not None:
                self.statement_rules(stmt.iftrue, true_id, stmt_id)
            if stmt.iffalse is not None:
                self.statement_rules(stmt.iffalse, false_id, stmt_id)

        elif type(stmt) == c_ast.Switch:
            pass

        elif type(stmt) == c_ast.Assignment:
            lhs_id = self.next_id()
            rhs_id = self.next_id()
            self.rule_body.append('assignT({0}, {1}, {2}, {3})'.format(stmt_id, parent_id, lhs_id, rhs_id))
            self.statement_rules(stmt.lvalue, lhs_id, stmt_id)
            if stmt.op == c_lexer.CLexer.t_EQUALS:
                self.statement_rules(stmt.rvalue, rhs_id, stmt_id)
            else:
                binary_op = c_ast.BinaryOp(stmt.op[:-1], stmt.lvalue, stmt.rvalue)
                self.statement_rules(binary_op, rhs_id, stmt_id)

        elif type(stmt) == c_ast.FuncCall:
            args_block_id = self.next_id()
            self.rule_body.append('callT({0}, {1}, \'{2}\', {3})'.format(stmt_id, parent_id, stmt.name.name, args_block_id))
            self.rule_body.append('length({0}, {1})'.format(args_block_id, len(stmt.args.exprs)))
            arg_ids = [self.next_id() for arg in stmt.args.exprs]
            for idx in range(0, len(arg_ids)):
                self.statement_rules(stmt.args.exprs[idx], arg_ids[idx], stmt_id)
                if idx > 0:
                    self.rule_body.append('directly_after({0}, {1}, {2})'.format(arg_ids[idx], arg_ids[idx - 1], args_block_id))

        elif type(stmt) == c_ast.UnaryOp:
            if stmt.op == '*':
                addr_expr_id = self.next_id()
                self.rule_body.append('memoryT({0}, {1}, {2})'.format(stmt_id, parent_id, addr_expr_id))
                self.statement_rules(stmt.expr, addr_expr_id, stmt_id)
            elif stmt.op in ['p++', 'p--']:
                assignment = c_ast.Assignment(c_lexer.CLexer.t_EQUALS,
                                              stmt.expr,
                                              c_ast.BinaryOp('+',
                                                             stmt.expr,
                                                             c_ast.Constant('int', 1 if stmt.op == 'p++' else -1)))
                self.statement_rules(assignment, stmt_id, parent_id)
            else:
                self.operation_rules(stmt_id, parent_id, [stmt.expr], stmt.op)

        elif type(stmt) == c_ast.BinaryOp:
            if stmt.op == '-':
                stmt.op = '+'
                if type(stmt.right) == c_ast.Constant and stmt.right.type in ['int', 'float']:
                    stmt.right.value = '-' + stmt.right.value
                else:
                    stmt.right = c_ast.UnaryOp('-', stmt.right)

            self.operation_rules(stmt_id, parent_id, [stmt.left, stmt.right], stmt.op)

        elif type(stmt) == c_ast.TernaryOp:
            cond_id = self.next_id()
            true_id = self.next_id()
            false_id = self.next_id()
            self.rule_body.append('ternaryOperatorT({0}, {1}, {2}, {3}, {4})'.format(stmt_id, parent_id, cond_id, true_id, false_id))
            self.statement_rules(stmt.cond, cond_id, stmt_id)
            self.statement_rules(stmt.iftrue, true_id, stmt_id)
            self.statement_rules(stmt.iffalse, false_id, stmt_id)

        elif type(stmt) == c_ast.ID:
            if stmt.name[0] == self.SPECIAL_VARIABLE_START:
                self.rule_body.append('{0} = {1}'.format(stmt.name[1:].title(), stmt_id))
            else:
                self.rule_body.append('identT({0}, {1}, {2})'.format(stmt_id, parent_id, stmt.name.title()))
                self.variable_ids.add(stmt.name.title())

        elif type(stmt) == c_ast.Constant:
            if stmt.type == 'int':
                try:
                    val = int(stmt.value)
                except ValueError:
                    val = int(stmt.value, 16)
                self.rule_body.append('numericLiteralT({0}, {1}, {2})'.format(stmt_id, parent_id, val))
        elif type(stmt) == c_ast.Break:
            self.rule_body.append('breakT({0}, {1})'.format(stmt_id, parent_id))
        elif type(stmt) == c_ast.Return:
            op_id = self.id_generator.next_id()
            self.rule_body.append('returnT({0}, {1}, {2})'.format(stmt_id, parent_id, op_id))
            self.statement_rules(stmt.expr, op_id, stmt_id)
        elif type(stmt) == c_ast.Label:
            self.parse_label(stmt)
        else:
            assert False, "unrecognized stmt: {0}\n".format(type(stmt))
Beispiel #28
0
    def visit_If(self, n):
        logger.debug('types(before branch): {}'.format(self._types))
        logger.debug('Line {}: if({})'.format(n.coord.line, _code_generator.visit(n.cond)))

        # update pc value updPC
        before_pc = self._pc
        self._pc = self._update_pc(self._pc, self._types, n.cond)

        before_types = self._types.copy()
        # corresponds to \Gamma_0 in paper
        types_0 = self._types.copy()
        # promote the shadow distances of the assigned variables to *
        shadow_finder = _ExpressionFinder(lambda node: isinstance(node, c_ast.Assignment) and node.lvalue)
        for assign_node in shadow_finder.visit(n):
            if isinstance(assign_node.lvalue, c_ast.ID):
                varname = assign_node.lvalue.name
            elif isinstance(assign_node.lvalue, c_ast.ArrayRef):
                varname = assign_node.lvalue.name.name
            else:
                raise NotImplementedError(
                    'Assign node lvalue type not supported {}'.format(type(assign_node.lvalue)))
            align, shadow = types_0.get_distance(varname)
            types_0.update_distance(varname, align, '*')

        if self._pc and not before_pc:
            self._types = types_0

        # backup the current types before entering the true or false branch
        cur_types = self._types.copy()

        self._inserted_query_assumes.append([])
        # add current condition for simplification
        self._types.apply(n.cond, True)
        # to be used in if branch transformation assert(e^aligned);
        aligned_true_cond = _ExpressionReplacer(self._types, True).visit(
            copy.deepcopy(n.cond))
        self.visit(n.iftrue)
        true_types = self._types
        logger.debug('types(true branch): {}'.format(true_types))
        true_assumes = self._inserted_query_assumes.pop()

        self._inserted_query_assumes.append([])
        # revert current types back to enter the false branch
        self._types = cur_types
        self._types.apply(n.cond, False)
        if n.iffalse:
            logger.debug('Line: {} else'.format(n.iffalse.coord.line))
            self.visit(n.iffalse)
        # to be used in else branch transformation assert(not (e^aligned));
        aligned_false_cond = _ExpressionReplacer(self._types, True).visit(copy.deepcopy(n.cond))
        logger.debug('types(false branch): {}'.format(self._types))
        false_types = self._types.copy()
        self._types.merge(true_types)
        logger.debug('types(after merge): {}'.format(self._types))
        false_assumes = self._inserted_query_assumes.pop()

        exp_checker = _ExpressionFinder(
            lambda node: isinstance(node, c_ast.ArrayRef) and '__SHADOWDP_' in node.name.name and
                         self._parameters[2] in node.name.name)

        if self._loop_level == 0:
            if self._pc and not before_pc:
                # insert c_s
                c_s = self._instrument(before_types, types_0, before_pc)
                if_index = self._parents[n].block_items.index(n)
                self._parents[n].block_items[if_index:if_index] = c_s
                for statement in c_s:
                    self._inserted.add(statement)
                self._inserted.add(n)
                # insert c_shadow
                shadow_cond = _ExpressionReplacer(types_0, False).visit(
                    copy.deepcopy(n.cond))
                shadow_branch = c_ast.If(cond=shadow_cond,
                                         iftrue=c_ast.Compound(
                                             block_items=copy.deepcopy(n.iftrue.block_items)),
                                         iffalse=c_ast.Compound(
                                             block_items=copy.deepcopy(n.iffalse.block_items)) if n.iffalse else None)
                shadow_branch_generator = _ShadowBranchGenerator(
                    {name for name, (_, shadow) in types_0.variables() if shadow == '*'},
                    types_0)
                shadow_branch_generator.visit(shadow_branch)
                if_index = self._parents[n].block_items.index(n)
                self._parents[n].block_items.insert(if_index + 1, shadow_branch)
                self._inserted.add(shadow_branch)

                # insert assume functions before the shadow branch
                for query_node in exp_checker.visit(shadow_cond):
                    assume_functions = self._assume_query(query_node)
                    index = self._parents[n].block_items.index(n) + 1
                    self._parents[n].block_items[index:index] = assume_functions
                    for assume_function in assume_functions:
                        self._inserted.add(assume_function)

            # create else branch if doesn't exist
            n.iffalse = n.iffalse if n.iffalse else c_ast.Compound(block_items=[])

            # insert assert and assume functions to corresponding branch
            for aligned_cond in (aligned_true_cond, aligned_false_cond):
                block_node = n.iftrue if aligned_cond is aligned_true_cond else n.iffalse
                # insert the assertion
                assert_body = c_ast.ExprList(exprs=[aligned_cond]) if aligned_cond is aligned_true_cond else \
                    c_ast.UnaryOp(op='!', expr=c_ast.ExprList(exprs=[aligned_cond]))

                block_node.block_items.insert(0, c_ast.FuncCall(name=c_ast.ID(self._func_map['assert']),
                                                                args=assert_body))
                # if the expression contains `query` variable,
                # add assume functions on __SHADOWDP_ALIGNED_DISTANCE_query and __SHADOWDP_SHADOW_DISTANCE_query
                inserted = true_assumes if aligned_cond is aligned_true_cond else false_assumes
                self._inserted_query_assumes.append(inserted)
                for query_node in exp_checker.visit(aligned_cond):
                    assume_functions = self._assume_query(query_node)
                    block_node.block_items[0:0] = assume_functions
                self._inserted_query_assumes.pop()

            # instrument statements for updating aligned or shadow distance variables (Instrumentation rule)
            for types in (true_types, false_types):
                block_node = n.iftrue if types is true_types else n.iffalse
                inserted = true_assumes if types is true_types else false_assumes
                self._inserted_query_assumes.append(inserted)
                instruments = self._instrument(types, self._types, self._pc)
                block_node.block_items.extend(instruments)
                for instrument in instruments:
                    self._inserted.add(instrument)
                self._inserted_query_assumes.pop()

        self._pc = before_pc
Beispiel #29
0
 def take_address_of(self, expr):
     return c_ast.UnaryOp("&", expr)
Beispiel #30
0
def make_call_from_mutator_decl(arg_name, decl):
    name = c_ast.ID(decl.name)
    args = c_ast.ExprList(exprs=[c_ast.UnaryOp("&", c_ast.ID(arg_name))])
    call = c_ast.FuncCall(name, args)
    return call