void goto_symext::symex_free(const expr2tc &expr) { const code_free2t &code = to_code_free2t(expr); // Trigger 'free'-mode dereference of this pointer. Should generate various // dereference failure callbacks. expr2tc tmp = code.operand; dereference(tmp, dereferencet::FREE); // Don't rely on the output of dereference in free mode; instead fetch all // the internal dereference state for pointed at objects, and creates claims // that if pointed at, their offset is zero. internal_deref_items.clear(); tmp = code.operand; // Create temporary, dummy, dereference tmp = dereference2tc(get_uint8_type(), tmp); dereference(tmp, dereferencet::INTERNAL); // Only add assertions to check pointer offset if pointer check is enabled if(!options.get_bool_option("no-pointer-check")) { for(auto const &item : internal_deref_items) { guardt g = cur_state->guard; g.add(item.guard); expr2tc offset = item.offset; expr2tc eq = equality2tc(offset, gen_ulong(0)); g.guard_expr(eq); claim(eq, "Operand of free must have zero pointer offset"); } } // Clear the alloc bit, and set the deallocated bit. type2tc sym_type = type2tc(new array_type2t(get_bool_type(), expr2tc(), true)); expr2tc ptr_obj = pointer_object2tc(pointer_type2(), code.operand); dereference(ptr_obj, dereferencet::READ); symbol2tc dealloc_sym(sym_type, deallocd_arr_name); index2tc dealloc_index_expr(get_bool_type(), dealloc_sym, ptr_obj); expr2tc truth = gen_true_expr(); symex_assign(code_assign2tc(dealloc_index_expr, truth), true); symbol2tc valid_sym(sym_type, valid_ptr_arr_name); index2tc valid_index_expr(get_bool_type(), valid_sym, ptr_obj); expr2tc falsity = gen_false_expr(); symex_assign(code_assign2tc(valid_index_expr, falsity), true); }
void goto_symext::symex_free(const expr2tc &expr) { const code_free2t &code = to_code_free2t(expr); // Trigger 'free'-mode dereference of this pointer. Should generate various // dereference failure callbacks. expr2tc tmp = code.operand; dereference(tmp, false, true); // Don't rely on the output of dereference in free mode; instead fetch all // the internal dereference state for pointed at objects, and creates claims // that if pointed at, their offset is zero. internal_deref_items.clear(); tmp = code.operand; // Create temporary, dummy, dereference tmp = dereference2tc(get_uint8_type(), tmp); dereference(tmp, false, false, true); // 'internal' dereference for (const auto &item : internal_deref_items) { guardt g = cur_state->guard; g.add(item.guard); expr2tc offset = item.offset; expr2tc eq = equality2tc(offset, zero_ulong); g.guard_expr(eq); claim(eq, "Operand of free must have zero pointer offset"); } // Clear the alloc bit, and set the deallocated bit. guardt guard; type2tc sym_type = type2tc(new array_type2t(get_bool_type(), expr2tc(), true)); pointer_object2tc ptr_obj(pointer_type2(), code.operand); symbol2tc dealloc_sym(sym_type, deallocd_arr_name); index2tc dealloc_index_expr(get_bool_type(), dealloc_sym, ptr_obj); expr2tc truth = true_expr; symex_assign_rec(dealloc_index_expr, truth, guard); symbol2tc valid_sym(sym_type, valid_ptr_arr_name); index2tc valid_index_expr(get_bool_type(), valid_sym, ptr_obj); expr2tc falsity = false_expr; symex_assign_rec(valid_index_expr, falsity, guard); }
smt_astt smt_convt::convert_byte_extract(const expr2tc &expr) { const byte_extract2t &data = to_byte_extract2t(expr); assert(is_scalar_type(data.source_value) && "Byte extract now only works on " "scalar variables"); if (!is_constant_int2t(data.source_offset)) { expr2tc source = data.source_value; unsigned int src_width = source->type->get_width(); if (!is_bv_type(source)) { source = typecast2tc(get_uint_type(src_width), source); } // The approach: the argument is now a bitvector. Just shift it the // appropriate amount, according to the source offset, and select out the // bottom byte. expr2tc offs = data.source_offset; // Endian-ness: if we're in non-"native" endian-ness mode, then flip the // offset distance. The rest of these calculations will still apply. if (data.big_endian) { auto data_size = type_byte_size(*source->type); constant_int2tc data_size_expr(source->type, data_size - 1); sub2tc sub(source->type, data_size_expr, offs); offs = sub; } if (offs->type->get_width() != src_width) // Z3 requires these two arguments to be the same width offs = typecast2tc(source->type, data.source_offset); lshr2tc shr(source->type, source, offs); smt_astt ext = convert_ast(shr); smt_astt res = mk_extract(ext, 7, 0, convert_sort(get_uint8_type())); return res; } const constant_int2t &intref = to_constant_int2t(data.source_offset); unsigned width; width = data.source_value->type->get_width(); uint64_t upper, lower; if (!data.big_endian) { upper = ((intref.constant_value.to_long() + 1) * 8) - 1; //((i+1)*w)-1; lower = intref.constant_value.to_long() * 8; //i*w; } else { uint64_t max = width - 1; upper = max - (intref.constant_value.to_long() * 8); //max-(i*w); lower = max - ((intref.constant_value.to_long() + 1) * 8 - 1); //max-((i+1)*w-1); } smt_astt source = convert_ast(data.source_value);; if (int_encoding) { std::cerr << "Refusing to byte extract in integer mode; re-run in " "bitvector mode" << std::endl; abort(); } else { if (is_bv_type(data.source_value)) { ; } else if (is_fixedbv_type(data.source_value)) { ; } else if (is_bool_type(data.source_value)) { // We cdan extract a byte from a bool -- zero or one. typecast2tc cast(get_uint8_type(), data.source_value); source = convert_ast(cast); } else { std::cerr << "Unrecognized type in operand to byte extract." << std::endl; data.dump(); abort(); } unsigned int sort_sz = data.source_value->type->get_width(); if (sort_sz <= upper) { smt_sortt s = mk_sort(SMT_SORT_BV, 8, false); return mk_smt_symbol("out_of_bounds_byte_extract", s); } else { return mk_extract(source, upper, lower, convert_sort(expr->type)); } } }