def extract_hdr(self, ctx, merged_args): hdr = merged_args[self.hdr_param_name].p4_val # apply the local and parent extern type ctxs for type_name, p4_type in self.extern_ctx.items(): ctx.add_type(type_name, ctx.resolve_type(p4_type)) for type_name, p4_type in self.type_ctx.items(): ctx.add_type(type_name, ctx.resolve_type(p4_type)) # advance the header index if a next field has been accessed hdr_stack = detect_hdr_stack_next(ctx, hdr) if hdr_stack: compare = hdr_stack.locals[ "nextIndex"] >= hdr_stack.locals["size"] if z3.simplify(compare) == z3.BoolVal(True): raise ParserException("Index out of bounds!") # grab the hdr value hdr_expr = ctx.resolve_expr(hdr) hdr_expr.activate() bind_const = z3.Const(f"{self.name}_{self.hdr_param_name}", hdr_expr.z3_type) hdr_expr.bind(bind_const) # advance the stack, if it exists if hdr_stack: hdr_stack.locals["lastIndex"] = hdr_stack.locals[ "nextIndex"] hdr_stack.locals["nextIndex"] += 1 self.call_counter += 1
def eval(self, ctx): cond = z3.simplify(ctx.resolve_expr(self.cond)) forward_cond_copy = ctx.tmp_forward_cond then_vars = None if not z3.is_false(cond): var_store = ctx.checkpoint() ctx.tmp_forward_cond = z3.And(forward_cond_copy, cond) try: self.then_block.eval(ctx) except ParserException: RejectState().eval(ctx) if not(ctx.has_returned or ctx.get_exited()): then_vars = ctx.get_attrs() ctx.set_exited(False) ctx.has_returned = False ctx.restore(var_store) if not z3.is_true(cond): var_store = ctx.checkpoint() ctx.tmp_forward_cond = z3.And(forward_cond_copy, z3.Not(cond)) try: self.else_block.eval(ctx) except ParserException: RejectState().eval(ctx) if ctx.get_exited() or ctx.has_returned: ctx.restore(var_store) ctx.set_exited(False) ctx.has_returned = False ctx.tmp_forward_cond = forward_cond_copy if then_vars: merge_attrs(ctx, cond, then_vars)
def eval(self, ctx): cond = z3.simplify( z3.And(z3.Not(z3.Or(*ctx.forward_conds)), ctx.tmp_forward_cond)) if not z3.is_false(cond): ctx.return_states.append((cond, ctx.copy_attrs())) ctx.has_returned = True ctx.forward_conds.append(ctx.tmp_forward_cond)
def eval(self, p4_state): context = p4_state.current_context() cond = z3.simplify(p4_state.resolve_expr(self.cond)) forward_cond_copy = context.tmp_forward_cond then_vars = None if not cond == z3.BoolVal(False): var_store, contexts = p4_state.checkpoint() context.tmp_forward_cond = z3.And(forward_cond_copy, cond) try: self.then_block.eval(p4_state) except ParserException: RejectState().eval(p4_state) if not (context.has_returned or p4_state.has_exited): then_vars = p4_state.get_attrs() p4_state.has_exited = False context.has_returned = False p4_state.restore(var_store, contexts) if not cond == z3.BoolVal(True): var_store, contexts = p4_state.checkpoint() context.tmp_forward_cond = z3.And(forward_cond_copy, z3.Not(cond)) try: self.else_block.eval(p4_state) except ParserException: RejectState().eval(p4_state) if p4_state.has_exited or context.has_returned: p4_state.restore(var_store, contexts) p4_state.has_exited = False context.has_returned = False context.tmp_forward_cond = forward_cond_copy if then_vars: merge_attrs(p4_state, cond, then_vars)
def eval(self, p4_state): context = p4_state.current_context() if self.expr is None: expr = None else: # resolve the expr before restoring the state expr = p4_state.resolve_expr(self.expr) if isinstance(context.return_type, z3.BitVecSortRef): expr = z3_cast(expr, context.return_type) # we return a complex typed expression list, instantiate if isinstance(expr, list): instance = gen_instance(p4_state, "undefined", context.return_type) instance.set_list(expr) expr = instance cond = z3.simplify( z3.And(z3.Not(z3.Or(*context.forward_conds)), context.tmp_forward_cond)) if not cond == z3.BoolVal(False): context.return_states.append((cond, p4_state.copy_attrs())) if expr is not None: context.return_exprs.append((cond, expr)) context.has_returned = True context.forward_conds.append(context.tmp_forward_cond)
def eval_callable(self, ctx, merged_args, var_buffer): # tables are a little bit special since they also have attributes # so what we do here is first initialize the key hit = self.eval_keys(ctx) self.locals["hit"] = z3.simplify(hit) self.locals["miss"] = z3.Not(hit) # then execute the table as the next expression in the chain self.eval_table(ctx)
def eval(self, p4_state): # FIXME: This checkpointing should not be necessary # Figure out what is going on var_store, contexts = p4_state.checkpoint() forward_conds = [] tmp_forward_conds = [] for context in reversed(p4_state.contexts): context.copy_out(p4_state) forward_conds.extend(context.forward_conds) tmp_forward_conds.append(context.tmp_forward_cond) context = p4_state.current_context() cond = z3.simplify( z3.And(z3.Not(z3.Or(*forward_conds)), z3.And(*tmp_forward_conds))) if not cond == z3.BoolVal(False): p4_state.exit_states.append((cond, p4_state.get_z3_repr())) p4_state.has_exited = True p4_state.restore(var_store, contexts) context.forward_conds.append(context.tmp_forward_cond)
def eval(self, ctx): # FIXME: This checkpointing should not be necessary # Figure out what is going on var_store = ctx.checkpoint() forward_conds = [] tmp_forward_conds = [] sub_ctx = ctx while not isinstance(sub_ctx, StaticContext): sub_ctx.copy_out(ctx) forward_conds.extend(sub_ctx.forward_conds) tmp_forward_conds.append(sub_ctx.tmp_forward_cond) sub_ctx = sub_ctx.parent_ctx cond = z3.simplify( z3.And(z3.Not(z3.Or(*forward_conds)), z3.And(*tmp_forward_conds))) if not z3.is_false(cond): ctx.add_exit_state(cond, ctx.get_p4_state().get_members(ctx)) ctx.set_exited(True) ctx.restore(var_store) ctx.forward_conds.append(ctx.tmp_forward_cond)
def eval(self, p4_state): cond = z3.simplify(p4_state.resolve_expr(self.cond)) # handle side effects for function and table calls if cond == z3.BoolVal(False): return p4_state.resolve_expr(self.else_val) if cond == z3.BoolVal(True): return p4_state.resolve_expr(self.then_val) var_store, chain_copy = p4_state.checkpoint() context = p4_state.current_context() forward_cond_copy = context.tmp_forward_cond context.tmp_forward_cond = z3.And(forward_cond_copy, cond) then_expr = p4_state.resolve_expr(self.then_val) then_vars = p4_state.get_attrs() p4_state.restore(var_store, chain_copy) context.tmp_forward_cond = forward_cond_copy else_expr = p4_state.resolve_expr(self.else_val) merge_attrs(p4_state, cond, then_vars) return handle_mux(cond, then_expr, else_expr)
def eval(self, ctx): if self.expr is None: expr = None else: # resolve the expr before restoring the state expr = ctx.resolve_expr(self.expr) if isinstance(ctx.return_type, z3.BitVecSortRef): expr = z3_cast(expr, ctx.return_type) # we return a complex typed expression list, instantiate if isinstance(expr, list): # name is meaningless here so keep it empty instance = ctx.gen_instance("", ctx.return_type) instance.set_list(expr) expr = instance cond = z3.simplify(z3.And(z3.Not(z3.Or(*ctx.forward_conds)), ctx.tmp_forward_cond)) if not z3.is_false(cond): ctx.return_states.append((cond, ctx.copy_attrs())) if expr is not None: ctx.return_exprs.append((cond, expr)) ctx.has_returned = True ctx.forward_conds.append(ctx.tmp_forward_cond)