Beispiel #1
0
def ConvertShortCircuitIf(if_stmt: c_ast.If, parent: c_ast.Node, id_gen: common.UniqueId):
    cond = if_stmt.cond
    if isinstance(cond, c_ast.UnaryOp) and cond.op == "!":
        # for a not not just swap the branches
        if_stmt.cond = cond.expr
        if_stmt.iffalse, if_stmt.iftrue = if_stmt.iftrue, if_stmt.iffalse
        ConvertShortCircuitIf(if_stmt, parent, id_gen)
        return

    if not isinstance(cond, c_ast.BinaryOp):
        return

    if cond.op != "&&" and cond.op != "||":
        return

    labelnext = id_gen.next("branch")
    if cond.op == "&&":
        if_stmt2 = c_ast.If(cond.left, c_ast.Goto(labelnext), if_stmt.iffalse)
    else:
        assert cond.op == "||"
        if_stmt2 = c_ast.If(cond.left, if_stmt.iftrue, c_ast.Goto(labelnext))
    if_stmt.cond = cond.right

    stmts = common.GetStatementList(parent)
    # this is easy to fix but basically guaranteed after running IfTransform
    assert stmts, parent
    pos = stmts.index(if_stmt)
    stmts[pos:pos + 1] = [if_stmt2, c_ast.Label(labelnext, c_ast.EmptyStatement()), if_stmt]
    ConvertShortCircuitIf(if_stmt2, parent, id_gen)
    ConvertShortCircuitIf(if_stmt, parent, id_gen)
Beispiel #2
0
        def visit_Compound(self, node):
            to_chain = []

            for n in node.block_items:
                if type(n) == c_ast.If:
                    to_chain.append(n)
                    self.generic_visit(n)

            if len(to_chain) > 1:
                for n in to_chain:
                    node.block_items.remove(n)

                first_if = to_chain[0]
                chained_if = c_ast.If(first_if.cond,
                                      iftrue=first_if.iftrue,
                                      iffalse=None)
                prev_if = chained_if
                node.block_items.append(chained_if)

                for n in to_chain[1:-1]:
                    new_if = c_ast.If(n.cond, iftrue=n.iftrue, iffalse=None)
                    prev_if.iffalse = new_if
                    prev_if = new_if

                last_if = to_chain[-1]
                prev_if.iffalse = c_ast.If(last_if.cond,
                                           iftrue=last_if.iftrue,
                                           iffalse=None)
Beispiel #3
0
 def insertTest(self,block,functionName,varVals,varTypes,timer):
     #Fork call
     cFork=c_ast.Assignment( lvalue=c_ast.ID(name='child_pid'), op='=', rvalue=c_ast.FuncCall( c_ast.ID(name='fork'), args=None))
     #Child
     if self.functype=='int' or self.functype=="bool":
         printLeft=c_ast.Constant(type="char",value='"'+"%d" +'"')
     elif self.functype=='float' or self.functype=='double':
         printLeft=c_ast.Constant(type="char",value='"'+"%f" +'"')
     else:
         printLeft=c_ast.Constant(type="char",value='"'+"%d" +'"')
     
     expressList = list(c_ast.Constant(type=varTypes[i],value=str(varVals[i])) for i in range(len(varVals)))
     funcCall = c_ast.FuncCall(c_ast.ID(name=functionName),c_ast.ExprList(expressList))
     expressList = [printLeft,funcCall]        
     funcCall = c_ast.FuncCall(c_ast.ID(name="printf"),c_ast.ExprList(expressList))
     
     funcCall2 = c_ast.FuncCall(c_ast.ID(name="exit"),c_ast.ExprList([c_ast.Constant(type='int',value='0')]))
     #Parent
     cAlarm=c_ast.FuncCall( c_ast.ID(name='alarm'),c_ast.ExprList([c_ast.Constant(type='int',value=str(timer))]))
     cWait=c_ast.FuncCall( c_ast.ID(name='wait'),c_ast.ExprList([c_ast.ID(name='0')]))
     #IFs
     if_false= c_ast.If( c_ast.BinaryOp(left=c_ast.ID(name='child_pid'),op='==',right= c_ast.Constant(type='int',value='0')), c_ast.Compound([funcCall,funcCall2]),iffalse=None)
     if_ini=c_ast.If( c_ast.BinaryOp(left=c_ast.ID(name='child_pid'),op='>',right= c_ast.Constant(type='int',value='0')), c_ast.Compound([cAlarm,cWait]),iffalse=if_false)
     block.body.block_items.insert(1,if_ini)
     block.body.block_items.insert(1,cFork)
Beispiel #4
0
 def insertTest(self,block,functionName,varVals,varTypes,timer,preOut,testId):
     #Fork call
     cFork=c_ast.Assignment( lvalue=c_ast.ID(name='child_pid'), op='=', rvalue=c_ast.FuncCall( c_ast.ID(name='fork'), args=None))
     #Child
     ##stdout = freopen("out.txt", "w", stdout);
     if self.functype=='int':
         printLeft=c_ast.Constant(type="char",value='"'+"%d" +'"')
     elif self.functype=='float' or self.functype=='double':
         printLeft=c_ast.Constant(type="char",value='"'+"%f" +'"')
     else:
         printLeft=c_ast.Constant(type="char",value='"'+"%d" +'"')
     fileOut=c_ast.Constant(type="char",value='"'+preOut +'.' +testId+".out.txt" +'"')
     fileW=c_ast.Constant(type="char",value='"'+"w" +'"')
     fileStdout=c_ast.ID(name='stdout')
     expressList = [fileOut,fileW,fileStdout]
     freopenC = c_ast.FuncCall(c_ast.ID(name="freopen"),c_ast.ExprList(expressList))
     outReassign=c_ast.Assignment( lvalue=fileStdout, op='=', rvalue=freopenC)
     ##mainfake()
     expressList = list(c_ast.Constant(type=varTypes[i],value=str(varVals[i])) for i in range(len(varVals)))
     funcCall = c_ast.FuncCall(c_ast.ID(name=functionName),c_ast.ExprList(expressList))
     expressList = [printLeft,funcCall]        
     funcCall = c_ast.FuncCall(c_ast.ID(name="printf"),c_ast.ExprList(expressList))
     ##exit(0)
     funcCall2 = c_ast.FuncCall(c_ast.ID(name="exit"),c_ast.ExprList([c_ast.Constant(type='int',value='0')]))
     #Parent
     cAlarm=c_ast.FuncCall( c_ast.ID(name='alarm'),c_ast.ExprList([c_ast.Constant(type='int',value=str(timer))]))
     cWait=c_ast.FuncCall( c_ast.ID(name='wait'),c_ast.ExprList([c_ast.ID(name='0')]))
     #IFs
     if_false= c_ast.If( c_ast.BinaryOp(left=c_ast.ID(name='child_pid'),op='==',right= c_ast.Constant(type='int',value='0')), c_ast.Compound([outReassign,funcCall,funcCall2]),iffalse=None)
     if_ini=c_ast.If( c_ast.BinaryOp(left=c_ast.ID(name='child_pid'),op='>',right= c_ast.Constant(type='int',value='0')), c_ast.Compound([cAlarm,cWait]),iffalse=if_false)
     block.body.block_items.insert(1,if_ini)
     block.body.block_items.insert(1,cFork)
Beispiel #5
0
 def visit_Assignment(self, node):
     if self.inner_for:
         self.remove_node()
         if self.begin:
             if not self.inner_begin_block:
                 self.inner_begin_block = c_ast.Compound([])
                 code = c_ast.If(c_ast.BinaryOp("==", self.inner_index, c_ast.Constant('int', '0')), self.inner_begin_block, None)
                 self.inner_for.stmt.block_items.insert(0, code)
             self.inner_begin_block.block_items.append(node)
         else:
             if not self.inner_end_block:
                 self.inner_end_block = c_ast.Compound([])
                 code = c_ast.If(c_ast.BinaryOp("==", self.inner_index, c_ast.BinaryOp('-', self.inner_limit, c_ast.Constant('int', '1'))), self.inner_end_block, None)
                 self.inner_for.stmt.block_items.append(code)
             self.inner_end_block.block_items.append(node)
Beispiel #6
0
    def add_jumps(self, jump_map: Dict[str, c_ast.Node]):

        for ghost_var, code in jump_map.items():
            #print(ghost_var)
            ghost_var_ast = c_ast.ID(ghost_var)
            self.update_ast.block_items.append(
                c_ast.If(ghost_var_ast, code, None))
Beispiel #7
0
def compile_node(lookup, decl_code, node):
    code = []
    stack = {}
    inargs = []
    pre = node.type + '_pre'
    post = node.type + '_post'

    compile_ast(lookup, stack, inargs, decl_code, code, pre)

    for word in node.quotation:
        compile_ast(lookup, stack, inargs, decl_code, code, word)
        compile_ast(lookup, stack, inargs, decl_code, code, node.type)
        call = code[-1]
        end_stack = deepcopy(stack)
        end_inargs = deepcopy(inargs)
        end_code = []
        compile_ast(lookup, end_stack, end_inargs, decl_code, end_code, post)
        outargs = [a for args in end_stack.values() for a in args]
        assign_results(outargs, end_code)
        end_code.append(c_ast.Return(None))
        end = c_ast.Compound(end_code)
        condition = c_ast.If(call, end, None)
        code[-1] = condition

    compile_ast(lookup, stack, inargs, decl_code, code, post)

    outargs = [a for args in stack.values() for a in args]
    name = gensym(node.type)
    fn = fndecl(name, inargs, outargs, code)
    decl_code.append(fn)
    lookup[name] = (inargs, outargs)
    return name
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 #9
0
def _build_handle_function(functions):
    """ Wraps the switch statement in a function definition

    """
    case_statement = _build_case(functions)
    available_check = c_ast.If(
        c_ast.BinaryOp(
            '<', c_ast.FuncCall(
                c_ast.ID('mailbox_available'),
                c_ast.ExprList([c_ast.Constant('int', '2')])
            ),
            c_ast.Constant('int', '4')
        ),
        c_ast.Return(None),
        None
    )
    handle_decl = c_ast.FuncDecl(
        None, c_ast.TypeDecl('_handle_events', [],
                             c_ast.IdentifierType(['void'])),
    )
    command_decl = c_ast.Decl('command', [], [], [],
                              c_ast.TypeDecl('command', [],
                                             c_ast.IdentifierType(['int'])),
                              [], [])
    command_read = _generate_read('command')
    body = c_ast.Compound([available_check,
                           command_decl,
                           command_read,
                           case_statement])
    return c_ast.FuncDef(handle_decl, [], body)
Beispiel #10
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 #11
0
def optimize_new(graph, tabDeg, myWhile):
    maxdeg = max_deg_of_list(tabDeg)
    while_node = myWhile.node_while
    peeling_deg = maxdeg + 1
    if peeling_deg == 0:
        myWhile.isOpt = True
        return 0
    initial_indices = []
    tabDegs = []
    nodelists = []
    listIf = []
    for i in range(peeling_deg):
        nodelists.append([])
        tabDegs.append([])
        initial_indices.append([])
    for i in range(len(tabDeg)):
        for j in range(len(initial_indices)):
            initial_indices[j].append(i)
    for deg in tabDeg:
        for i in range(len(tabDegs)):
            tabDegs[i].append(deg)
    for node in while_node.stmt.block_items:
        for i in range(peeling_deg):
            nodelists[i].append(node)
    for i in range(maxdeg):
        tbrm = []
        for init_ind in initial_indices[i]:
            if init_ind != -1:
                if tabDeg[init_ind] == i + 1:
                    tbrm.append(init_ind)
        for init_ind in tbrm:
            curr_ind = initial_indices[i].index(init_ind)
            (capture_tab, recover_tab) = captures(init_ind, myWhile.node_while,
                                                  tabDeg, graph)
            for capture in capture_tab:
                if capture[1] == -1 or capture[1] > i + 1:
                    for k in range(len(capture[0])):
                        nodelists[i].insert(curr_ind + 1, capture[0][k])
                        initial_indices[i].insert(curr_ind + 1, -1)
            for j in range(i + 1, peeling_deg):
                curr_ind = initial_indices[j].index(init_ind)
                for (recover, deg) in recover_tab:
                    if deg == -1 or deg > j:
                        nodelists[j].insert(curr_ind + 1, recover)
                        initial_indices[j].insert(curr_ind + 1, -1)
                nodelists[j].pop(curr_ind)
                initial_indices[j].pop(curr_ind)
        if DEBUG_LEVEL >= 3:
            print(maxdeg, nodelists, initial_indices)
        listIf.append(
            c_ast.If(while_node.cond, c_ast.Compound(nodelists[i]), None))
    listIf.append(
        c_ast.While(while_node.cond, c_ast.Compound(nodelists[maxdeg]), None))
    myWhile.parent[0].block_items.pop(myWhile.parent[1])
    listIf.reverse()
    for node in listIf:
        myWhile.parent[0].block_items.insert(myWhile.parent[1], node)
    myWhile.show()
    myWhile.isOpt = True
Beispiel #12
0
def add_jump_guard(ast_to_guard, phase_var, round_var, label):

    guarded_ast = c_ast.If(
        c_ast.BinaryOp(
            '&&', c_ast.BinaryOp('==', c_ast.ID(phase_var), c_ast.ID('PHASE')),
            c_ast.BinaryOp('==', c_ast.ID(round_var), c_ast.ID(label))),
        ast_to_guard, None)

    return c_ast.Compound([guarded_ast])
 def visit_If(self, n: ca.If) -> str:
     n2 = n
     if (n.iffalse and isinstance(n.iffalse, ca.Compound)
             and n.iffalse.block_items and len(n.iffalse.block_items) == 1
             and isinstance(n.iffalse.block_items[0], ca.If)):
         n2 = ca.If(cond=n.cond,
                    iftrue=n.iftrue,
                    iffalse=n.iffalse.block_items[0])
     return super().visit_If(n2)  # type: ignore
Beispiel #14
0
 def createOutputIf(self, expr):
     expressList = [c_ast.Constant(type='int', value='0')]
     funcCall = c_ast.FuncCall(c_ast.ID(name="assert"),
                               c_ast.ExprList(expressList))
     if_all = c_ast.If(c_ast.BinaryOp(left=c_ast.ID(name='__out_var'),
                                      op='==',
                                      right=expr),
                       c_ast.Compound([funcCall]),
                       iffalse=None)
     return (if_all)
Beispiel #15
0
 def visit_While(self, node):
     global global_trick_counter
     if isinstance(self.current_parent, c_ast.Compound):
         for i in xrange(len(self.current_parent.block_items)):
             if self.current_parent.block_items[i] == node:
                 if global_do_trick:
                     global_trick_counter -= 1
                     if global_trick_counter == 0:
                         self.current_parent.block_items[i] = c_ast.If(node.cond, node.stmt, None, node.coord)
                 else:
                     global_trick_counter+= 1;
Beispiel #16
0
    def test_nested_else_if_line_breaks(self):
        generator = c_generator.CGenerator()
        test_ast1 = c_ast.If(None, None, None)
        test_ast2 = c_ast.If(None, None, c_ast.If(None, None, None))
        test_ast3 = c_ast.If(None, None,
                             c_ast.If(None, None, c_ast.If(None, None, None)))
        test_ast4 = c_ast.If(
            None, c_ast.Compound([]),
            c_ast.If(None, c_ast.Compound([]),
                     c_ast.If(None, c_ast.Compound([]), None)))

        self.assertEqual(generator.visit(test_ast1), 'if ()\n  \n')
        self.assertEqual(generator.visit(test_ast2),
                         'if ()\n  \nelse\n  if ()\n  \n')
        self.assertEqual(generator.visit(test_ast3),
                         'if ()\n  \nelse\n  if ()\n  \nelse\n  if ()\n  \n')
        self.assertEqual(
            generator.visit(test_ast4),
            'if ()\n{\n}\nelse\n  if ()\n{\n}\nelse\n  if ()\n{\n}\n')
Beispiel #17
0
def ConvertWhileLoop(ast, id_gen: common.UniqueId):
    def IsWhileLoop(node, _):
        return isinstance(node, (c_ast.DoWhile, c_ast.While))

    candidates = common.FindMatchingNodesPostOrder(ast, ast, IsWhileLoop)
    for node, parent in candidates:
        loop_label = id_gen.next("while")
        test_label = loop_label + "_cond"
        exit_label = loop_label + "_exit"
        conditional = c_ast.If(node.cond, c_ast.Goto(loop_label), None)
        block = [c_ast.Label(loop_label, c_ast.EmptyStatement()), node.stmt,
                 c_ast.Label(test_label, c_ast.EmptyStatement()), conditional,
                 c_ast.Label(exit_label, c_ast.EmptyStatement())]
        if isinstance(node, c_ast.While):
            block = [c_ast.Goto(test_label)] + block
        common.ReplaceBreakAndContinue(node.stmt, node, test_label, exit_label)
        common.ReplaceNode(parent, node, c_ast.Compound(block))
Beispiel #18
0
 def replaceByPrint(self, ast):
     expressList = [
         c_ast.Constant(type='string', value='"[[REACHED]]"')
     ]
     ifexpress = c_ast.Assignment(op="=",
                                  lvalue=c_ast.ID(name="inst_flag"),
                                  rvalue=c_ast.Constant(type='int',
                                                        value='1'))
     self.funcCall.name = c_ast.ID(name="perror")
     self.funcCall.args = c_ast.ExprList(expressList)
     if_all = c_ast.If(c_ast.BinaryOp(left=c_ast.ID(name='inst_flag'),
                                      op='==',
                                      right=c_ast.Constant(type='int',
                                                           value='0')),
                       c_ast.Compound([self.funcCall, ifexpress]),
                       iffalse=None)
     for position, inst_block in enumerate(self.inst_block):
         inst_block[self.inst_pos[position]] = if_all
def addTestFunction(ast, expectedOutput, testFxn, initVars, initList):
    varList = []
    exprList = []
    fxnName = ''
    inFxn = False
    listi = 0
    for i in range(len(initVars)):
        v = initVars[i]
        if inFxn:
            exprList.append(c_ast.Constant('int', initList[listi]))
            listi += 1
            if (')' in v):
                inFxn = False
                newVar = c_ast.FuncCall(c_ast.ID(fxnName), c_ast.ExprList(exprList))
                varList.append(newVar)
                exprList = []
        else:
            if ('(' in v):
                fxnName = v[:v.index('(')]
                if (v[v.index('(')+1] != ')'):
                    inFxn = True
                    exprList.append(c_ast.Constant('int', initList[listi]))
                    listi += 1
                else:
                    newVar = c_ast.FuncCall(c_ast.ID(fxnName), c_ast.ExprList([]))
                    varList.append(newVar)
            else:
                newVar = c_ast.Assignment('=', c_ast.ID(v), c_ast.Constant('int', initList[listi]))
                listi += 1
                varList.append(newVar)
    fxnDecl = c_ast.FuncDecl(None, c_ast.TypeDecl('klee_test_entry', [], c_ast.IdentifierType(['void'])))
    fxnCall = c_ast.FuncCall(c_ast.ID(testFxn), c_ast.ExprList([]))
    binaryOp = c_ast.BinaryOp('==', fxnCall, c_ast.Constant('int', expectedOutput))
    ifFalse = c_ast.Compound([c_ast.FuncCall(c_ast.ID('klee_silent_exit'), c_ast.ExprList([c_ast.Constant('int', '0')]))])
    ifTrue = c_ast.Compound([])
    blockItems = []
    for v in varList:
        blockItems.append(v)
    blockItems.append(c_ast.If(binaryOp, ifTrue, ifFalse))
    fxnBody = c_ast.Compound(blockItems)
    fxnNode = c_ast.FuncDef(fxnDecl, None, fxnBody)
    ast.ext.append(fxnNode)
Beispiel #20
0
            def convert(i):

                if i >= n:
                    return

                item = node.stmt.block_items[i]

                # Item statement
                stmt = (c_ast.Compound(item.stmts, coord=item.coord)
                        if isinstance(item.stmts, list) else item.stmts)

                if i == (n - 1) and isinstance(item, c_ast.Default):
                    return stmt
                    
                if isinstance(item, c_ast.Case):
                    next = convert(i + 1)

                    ifcond = c_ast.BinaryOp('==', node.cond, item.expr,
                                            coord=item.expr.coord)
                    return c_ast.If(ifcond, stmt, next, coord=item.expr.coord)
Beispiel #21
0
def ConvertForLoop(ast, id_gen: common.UniqueId):
    candidates = common.FindMatchingNodesPostOrder(
        ast, ast, lambda n, _: isinstance(n, c_ast.For))
    for node, parent in candidates:
        loop_label = id_gen.next("for")
        next_label = loop_label + "_next"
        test_label = loop_label + "_cond"
        exit_label = loop_label + "_exit"
        goto = c_ast.Goto(loop_label)
        conditional = c_ast.If(node.cond, goto, None) if node.cond else goto
        block = ExtractForInitStatements(node.init) + [
            c_ast.Goto(test_label),
            c_ast.Label(loop_label, c_ast.EmptyStatement()), node.stmt,
            c_ast.Label(next_label, c_ast.EmptyStatement()),
            node.next if node.next else c_ast.EmptyStatement(),
            c_ast.Label(test_label, c_ast.EmptyStatement()), conditional,
            c_ast.Label(exit_label, c_ast.EmptyStatement())
        ]
        common.ReplaceBreakAndContinue(node.stmt, node, next_label, exit_label)
        common.ReplaceNode(parent, node, c_ast.Compound(block))
Beispiel #22
0
    def add_property(self,
                     property: c_ast.ExprList,
                     loop: c_ast.DoWhile or c_ast.While or c_ast.For,
                     slice: bool = True):
        """
		Adds the given expression to the end of the given loop. Note that by doing this, any previous property becomes
		unusable for our k-induction process.
		:param expression: The expression to be added.
		:param loop: The loop to add the property to.
		:param slice: Whether the code was sliced by Frama-C or not.
		"""
        if hasattr(loop, "stmt") and type(loop.stmt) is c_ast.Compound:
            if slice:
                SliceFuncCallUpdater().visit(property)
            property = self.join_expression_list("&&", property)
            property_check = c_ast.If(
                cond=property,
                iftrue=c_ast.Compound(
                    [c_ast.FuncCall(c_ast.ID("__VERIFIER_error"), None)]),
                iffalse=None)
            loop.stmt.block_items.append(property_check)
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)
Beispiel #24
0
def cfg_path_to_ast(cfg):
    """Generates a AST from a CFG path (No FileAST support, it handles 
    FuncDecl, If, While and no compound objects).

    Parameters
    ----------
    cfg : ControlFlowGraph
    """
    current_compound = c_ast.Compound([])
    ast = current_compound
    previous_compound = None

    nodes = list(nx.topological_sort(cfg))

    for n in nodes:

        if type(n) in {c_ast.FuncDef, c_ast.While, c_ast.If}:

            previous_compound = current_compound
            current_compound = c_ast.Compound([])

            if type(n) == c_ast.FuncDef:
                inner_ast = c_ast.FuncDef(n.decl, n.param_decls,
                                          current_compound)
            elif type(n) == c_ast.While:
                inner_ast = c_ast.While(n.cond, current_compound)
            elif type(n) == c_ast.If:
                inner_ast = c_ast.If(n.cond, current_compound, None)

            previous_compound.block_items.append(inner_ast)

        elif type(n) not in {
                ControlFlowGraph.FuncDefEnd, ControlFlowGraph.IfEnd,
                ControlFlowGraph.IfStart, ControlFlowGraph.WhileEnd
        }:

            current_compound.block_items.append(n)

    return ast
def perm_ins_block(fn: ca.FuncDef, ast: ca.FileAST, indices: Indices,
                   region: Region, random: Random) -> bool:
    """Wrap a random range of statements within `if (1) { ... }` or
    `do { ... } while(0)`. Control flow can have remote effects, so this
    mostly ignores the region restriction."""
    cands: List[Block] = []

    def rec(block: Block) -> None:
        cands.append(block)
        for stmt in ast_util.get_block_stmts(block, False):
            ast_util.for_nested_blocks(stmt, rec)

    rec(fn.body)
    block = random.choice(cands)
    stmts = ast_util.get_block_stmts(block, True)
    decl_count = 0
    for stmt in stmts:
        if isinstance(stmt, (ca.Decl, ca.Pragma)):
            decl_count += 1
        else:
            break
    lo = random.randrange(decl_count, len(stmts) + 1)
    hi = random.randrange(decl_count, len(stmts) + 1)
    if hi < lo:
        lo, hi = hi, lo
    new_block = ca.Compound(block_items=stmts[lo:hi])
    if random.uniform(0, 1) < INS_BLOCK_DOWHILE_PROB and all(
            region.contains_node(n) for n in stmts[lo:hi]):
        cond = ca.Constant(type="int", value="0")
        stmts[lo:hi] = [
            ca.Pragma("sameline start"),
            ca.DoWhile(cond=cond, stmt=new_block),
            ca.Pragma("sameline end"),
        ]
    else:
        cond = ca.Constant(type="int", value="1")
        stmts[lo:hi] = [ca.If(cond=cond, iftrue=new_block, iffalse=None)]
    return True
Beispiel #26
0
def loop_peel(graph, list_deg, loop):
    """Peel the loop based on the maximum invariance degree"""
    peeling_deg = max_deg_of_list(list_deg) + 1
    if peeling_deg != 0:  # if loop can be peeled
        loop_node = loop.loop_node
        parent_index = loop.parent[1]  # index in the AST of the original loop
        loop.parent[0].block_items.pop(parent_index)  # remove the orignal loop from AST
        commands = init_commands(peeling_deg,
                                 loop_node.stmt.block_items)  # initialize all the commands in the body of the loop
        peel = []  # list of AST nodes for each peel
        for i in range(peeling_deg):
            peel_body = []  # list of commands for current peel
            for (node, ind) in commands[i]:
                # if the command can be peeled and has reached its peeling degree
                if ind != -1 and list_deg[ind] == i + 1:
                    (capture_tab, recover_tab) = captures(ind, loop_node.stmt.block_items, list_deg, graph)
                    add_new_vars(commands, i, node, ind, peeling_deg, capture_tab, recover_tab)
                peel_body.append(node)

            # if its the last peel, add the body to a while statement with the same cond exp as the original while loop
            if i == peeling_deg - 1:
                peel.append(c_ast.While(loop_node.cond, c_ast.Compound(peel_body)))
            else:  # if not last peel, add the body to an if statement with the same cond exp as the original while loop
                peel.append(c_ast.If(loop_node.cond, c_ast.Compound(peel_body), None))

        # if the loop contains a break/contiue, wrap the entire peeled loop inside of a while loop with the same cond
        # exp as the original
        if check_break(loop_node.stmt):
            peel = c_ast.While(loop_node.cond, c_ast.Compound(peel + [c_ast.Break()]), None)
            loop.parent[0].block_items.insert(parent_index, peel)
        else:
            for i in peel:  # add each peel to the modified AST
                loop.parent[0].block_items.insert(parent_index, i)
                parent_index = parent_index + 1

    loop.isOpt = True
Beispiel #27
0
def new_if(cond, iftrue, iffalse):
    return c_ast.If(cond, iftrue, iffalse)
Beispiel #28
0
    def visit_FuncDef(self, node):
        if (len(self.varList) < 1):
            return

        self.name = node.decl.name

        # find the correct function name
        if (self.name == self.function):
            for idx, item in enumerate(node.body.block_items):
                # find the return statement within that function
                if (isinstance(item, c_ast.Return)):
                    returnStatement = item
                    for var in self.varList:
                        outOfScope = False
                        varArr = var.split(' ')
                        # make sure all variables of the expression are in-scope
                        for v in varArr:
                            if any(scopeV in v for scopeV in
                                   self.outOfScopeVarList) and v != '':
                                outOfScope = True
                                break
                        if outOfScope:
                            # replace the return statement with a print of 0
                            node.body.block_items[idx] = c_ast.FuncCall(
                                c_ast.ID('fprintf'),
                                c_ast.ExprList([
                                    c_ast.ID('stdout'),
                                    c_ast.Constant('str', '"%d,"'),
                                    c_ast.Constant('str', '"0"')
                                ]))
                            break
                        else:
                            # replace the return statement with the first printed variable
                            node.body.block_items[idx] = c_ast.FuncCall(
                                c_ast.ID('fprintf'),
                                c_ast.ExprList([
                                    c_ast.ID('stdout'),
                                    c_ast.Constant('str', '"%d,"'),
                                    c_ast.Constant('str', var)
                                ]))
                            break
            # add the remaining print statements
            for var in self.varList[1:]:
                # make sure all variables of the expression are in-scope
                outOfScope = False
                varArr = var.split(' ')
                for v in varArr:
                    if any(scopeV in v
                           for scopeV in self.outOfScopeVarList) and v != '':
                        outOfScope = True
                        break
                # print 0 if a variable is out of scope
                if outOfScope:
                    node.body.block_items.append(
                        c_ast.FuncCall(
                            c_ast.ID('fprintf'),
                            c_ast.ExprList([
                                c_ast.ID('stdout'),
                                c_ast.Constant('str', '"%d,"'),
                                c_ast.Constant('str', '"0"')
                            ])))

# print the expression if all variables are in scope
                else:
                    if ('/' in var):
                        denom = var[var.index('/') + 1:]
                        binaryOp = c_ast.BinaryOp('==',
                                                  c_ast.Constant('str', denom),
                                                  c_ast.Constant('int', '0'))
                        ifTrue = c_ast.Compound([
                            c_ast.FuncCall(
                                c_ast.ID('fprintf'),
                                c_ast.ExprList([
                                    c_ast.ID('stdout'),
                                    c_ast.Constant('str', '"NaN,"')
                                ]))
                        ])
                        ifFalse = c_ast.Compound([
                            c_ast.FuncCall(
                                c_ast.ID('fprintf'),
                                c_ast.ExprList([
                                    c_ast.ID('stdout'),
                                    c_ast.Constant('str', '"%d,"'),
                                    c_ast.Constant('str', var)
                                ]))
                        ])
                        node.body.block_items.append(
                            c_ast.If(binaryOp, ifTrue, ifFalse))
                    else:
                        node.body.block_items.append(
                            c_ast.FuncCall(
                                c_ast.ID('fprintf'),
                                c_ast.ExprList([
                                    c_ast.ID('stdout'),
                                    c_ast.Constant('str', '"%d,"'),
                                    c_ast.Constant('str', var)
                                ])))
            # add a newline character and the original return statement at the end
            node.body.block_items.append(
                c_ast.FuncCall(
                    c_ast.ID('fprintf'),
                    c_ast.ExprList(
                        [c_ast.ID('stdout'),
                         c_ast.Constant('str', '"\\n"')])))
            node.body.block_items.append(returnStatement)
Beispiel #29
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 #30
0
    def _assume_query(self, query_node):
        """ instrument assume functions of query input (sensitivity guarantee) """
        assume_functions = []
        shadow_distance_node = copy.deepcopy(query_node)
        align_distance_node = copy.deepcopy(query_node)
        regex = re.compile(r'__SHADOWDP_[A-Z]+_DISTANCE_([_a-zA-Z][a-zA-Z0-9\[\]]*)')
        align_distance_node.name.name = regex.sub(r'__SHADOWDP_ALIGNED_DISTANCE_\g<1>', query_node.name.name)
        shadow_distance_node.name.name = regex.sub(r'__SHADOWDP_SHADOW_DISTANCE_\g<1>', query_node.name.name)
        common_assume = [
                c_ast.FuncCall(
                    name=c_ast.ID(self._func_map['assume']),
                    args=c_ast.ExprList(exprs=[c_ast.BinaryOp(op='<=',
                                                              left=align_distance_node,
                                                              right=c_ast.Constant('int', '1'))])),
                c_ast.FuncCall(
                    name=c_ast.ID(self._func_map['assume']),
                    args=c_ast.ExprList(exprs=[c_ast.BinaryOp(op='>=',
                                                              left=align_distance_node,
                                                              right=c_ast.Constant('int', '-1'))])),
                c_ast.FuncCall(
                    name=c_ast.ID(self._func_map['assume']),
                    args=c_ast.ExprList(exprs=[c_ast.BinaryOp(op='==',
                                                              left=shadow_distance_node,
                                                              right=align_distance_node)]))
            ]
        # insert following statements:
        # if (i == __SHADOWDP_index) {
        #   assume(__SHADOWDP_ALIGNED_DISTANCE_q[i] >= -1); assume(__SHADOWDP_ALIGNED_DISTANCE_q[i] <= 1);
        #   assume(__SHADOWDP_SHADOW_DISTANCE_q[i] == __SHADOWDP_ALIGNED_DISTANCE_q[i]);
        # }
        # else {
        #   assume(__SHADOWDP_ALIGNED_DISTANCE_q[i] == 0);
        #   assume(__SHADOWDP_SHADOW_DISTANCE_q[i] == __SHADOWDP_ALIGNED_DISTANCE_q[i]);
        # }
        if self._one_differ:
            if_block = c_ast.If(cond=c_ast.BinaryOp('==',
                                                    left=query_node.subscript,
                                                    right=c_ast.ID(name='__SHADOWDP_index')),
                                iftrue=c_ast.Compound(block_items=[]),
                                iffalse=c_ast.Compound(block_items=[]))
            if_block.iftrue.block_items = common_assume
            if_block.iffalse.block_items = [
                c_ast.FuncCall(
                    name=c_ast.ID(self._func_map['assume']),
                    args=c_ast.ExprList(exprs=[c_ast.BinaryOp(op='==',
                                                              left=shadow_distance_node,
                                                              right=align_distance_node)])),
                c_ast.FuncCall(
                    name=c_ast.ID(self._func_map['assume']),
                    args=c_ast.ExprList(exprs=[c_ast.BinaryOp(op='==',
                                                              left=align_distance_node,
                                                              right=c_ast.Constant('int', '0'))]))

            ]
            assume_functions.append(if_block)
        # insert following statements:
        # assume(__SHADOWDP_ALIGNED_DISTANCE_q[i] >= -1); assume(__SHADOWDP_ALIGNED_DISTANCE_q[i] <= 1);
        # assume(__SHADOWDP_SHADOW_DISTANCE_q[i] == __SHADOWDP_ALIGNED_DISTANCE_q[i]);
        else:
            assume_functions = common_assume
        # if assume function has already been inserted in this scope
        for inserted in self._inserted_query_assumes[-1]:
            if is_node_equal(assume_functions, inserted):
                return []
        self._inserted_query_assumes[-1].append(assume_functions)
        return assume_functions