int timer_create_portable(clockid_t clockid, struct sigevent *portable_evp, timer_t *timerid) { struct sigevent native_sigevent, *evp = portable_evp; if (!invalid_pointer(portable_evp) && (evp->sigev_notify == SIGEV_SIGNAL || evp->sigev_notify == SIGEV_THREAD_ID)) { native_sigevent = *portable_evp; evp = &native_sigevent; evp->sigev_signo = signum_pton(evp->sigev_signo); } return timer_create(clockid, evp, timerid); }
static void __init test_pointer(void) { plain(); null_pointer(); invalid_pointer(); symbol_ptr(); kernel_ptr(); struct_resource(); addr(); escaped_str(); hex_string(); mac(); ip(); uuid(); dentry(); struct_va_format(); struct_rtc_time(); struct_clk(); bitmap(); netdev_features(); flags(); }
void goto_checkt::pointer_validity_check( const dereference_exprt &expr, const guardt &guard) { if(!enable_pointer_check) return; const exprt &pointer=expr.op0(); const typet &pointer_type=to_pointer_type(ns.follow(pointer.type())); assert(base_type_eq(pointer_type.subtype(), expr.type(), ns)); local_bitvector_analysist::flagst flags= local_bitvector_analysis->get(t, pointer); const typet &dereference_type=pointer_type.subtype(); // For Java, we only need to check for null if(mode==ID_java) { if(flags.is_unknown() || flags.is_null()) { notequal_exprt not_eq_null(pointer, gen_zero(pointer.type())); add_guarded_claim( not_eq_null, "reference is null", "pointer dereference", expr.find_source_location(), expr, guard); } } else { if(flags.is_unknown() || flags.is_null()) { add_guarded_claim( not_exprt(null_pointer(pointer)), "dereference failure: pointer NULL", "pointer dereference", expr.find_source_location(), expr, guard); } if(flags.is_unknown()) add_guarded_claim( not_exprt(invalid_pointer(pointer)), "dereference failure: pointer invalid", "pointer dereference", expr.find_source_location(), expr, guard); if(flags.is_uninitialized()) add_guarded_claim( not_exprt(invalid_pointer(pointer)), "dereference failure: pointer uninitialized", "pointer dereference", expr.find_source_location(), expr, guard); if(mode != ID_java) { if(flags.is_unknown() || flags.is_dynamic_heap()) add_guarded_claim( not_exprt(deallocated(pointer, ns)), "dereference failure: deallocated dynamic object", "pointer dereference", expr.find_source_location(), expr, guard); if(flags.is_unknown() || flags.is_dynamic_local()) add_guarded_claim( not_exprt(dead_object(pointer, ns)), "dereference failure: dead object", "pointer dereference", expr.find_source_location(), expr, guard); } if(enable_bounds_check) { if(flags.is_unknown() || flags.is_dynamic_heap()) { exprt dynamic_bounds= or_exprt(dynamic_object_lower_bound(pointer), dynamic_object_upper_bound(pointer, dereference_type, ns)); add_guarded_claim( implies_exprt(malloc_object(pointer, ns), not_exprt(dynamic_bounds)), "dereference failure: dynamic object bounds", "pointer dereference", expr.find_source_location(), expr, guard); } } if(enable_bounds_check) { if(flags.is_unknown() || flags.is_dynamic_local() || flags.is_static_lifetime()) { exprt object_bounds= or_exprt(object_lower_bound(pointer), object_upper_bound(pointer, dereference_type, ns)); add_guarded_claim( or_exprt(dynamic_object(pointer), not_exprt(object_bounds)), "dereference failure: object bounds", "pointer dereference", expr.find_source_location(), expr, guard); } } } }
/* * For 32 bit flocks we are converting a portable/ARM struct flock to a MIPS struct flock: * * MIPS: ARM: * struct flock { struct flock_portable { * short l_type; short l_type; * * short l_whence; short l_whence; * off_t l_start; loff_t l_start; * off_t l_len; loff_t l_len; * long l_sysid; * * __kernel_pid_t l_pid; pid_t l_pid; * long pad[4]; * }; } * * which have identically sized structure members: * * For a 64 bit flocks we only have to deal with * a four byte padding in the ARM/Portable structure: * * MIPS: ARM: * struct flock64 { struct flock64_portable { * short l_type; short l_type; * short l_whence; short l_whence; * unsigned char __padding[4]; <---- NOTE * loff_t l_start; loff_t l_start; * loff_t l_len; loff_t l_len; * pid_t l_pid; pid_t l_pid; * } } */ int WRAP(fcntl)(int fd, int portable_cmd, ...) { int flags; va_list ap; void *arg; int mips_cmd; int result = 0; struct flock flock; /* Native MIPS structure */ struct flock64 flock64; /* Native MIPS structure */ char *portable_cmd_name = map_portable_cmd_to_name(portable_cmd); struct flock_portable *flock_portable = NULL; struct flock64_portable *flock64_portable = NULL; ALOGV(" "); ALOGV("%s(fd:%d, portable_cmd:%d:'%s', ...) {", __func__, fd, portable_cmd, portable_cmd_name); va_start(ap, portable_cmd); arg = va_arg(ap, void *); va_end(ap); mips_cmd = fcntl_cmd_pton(portable_cmd); switch(mips_cmd) { case F_GETLK: case F_SETLK: case F_SETLKW: flock_portable = (struct flock_portable *) arg; if (invalid_pointer(flock_portable)) { ALOGE("%s: flock_portable:%p == {NULL||-1}", __func__, flock_portable); errno = EFAULT; result = -1; goto done; } /* * Lock type and Whence are the same for all ARCHs * (F_RDLCK:0, F_WRLCK:1, F_UNLCK:2) * (SEEK_SET:0, SEEK_CUR:1, SEEK_END:2) */ flock.l_type = flock_portable->l_type; flock.l_whence = flock_portable->l_whence; flock.l_start = (off_t) flock_portable->l_start; flock.l_len = (off_t) flock_portable->l_len; flock.l_sysid = 0L; flock.l_pid = flock_portable->l_pid; /* Perhaps 0 would be better */ result = __fcntl64(fd, mips_cmd, (void *) &flock); flock_portable->l_type = flock.l_type; flock_portable->l_whence = flock.l_whence; flock_portable->l_start = flock.l_start; flock_portable->l_len = flock.l_len; flock_portable->l_pid = flock.l_pid; break; case F_GETLK64: case F_SETLK64: case F_SETLKW64: flock64_portable = (struct flock64_portable *) arg; if (invalid_pointer(flock_portable)) { ALOGE("%s: flock_portable:%p == {NULL||-1}", __func__, flock_portable); errno = EFAULT; result = -1; goto done; } /* * Lock type and Whence are the same for all ARCHs * (F_RDLCK:0, F_WRLCK:1, F_UNLCK:2) * (SEEK_SET:0, SEEK_CUR:1, SEEK_END:2) */ flock64.l_type = flock64_portable->l_type; flock64.l_whence = flock64_portable->l_whence; flock64.l_start = (off_t) flock64_portable->l_start; flock64.l_len = (off_t) flock64_portable->l_len; flock64.l_pid = flock64_portable->l_pid; /* Perhaps 0 would be better */ result = __fcntl64(fd, mips_cmd, (void *) &flock); flock64_portable->l_type = flock64.l_type; flock64_portable->l_whence = flock64.l_whence; flock64_portable->l_start = flock64.l_start; flock64_portable->l_len = flock64.l_len; flock64_portable->l_pid = flock64.l_pid; break; case F_SETFL: flags = fcntl_flags_pton((int)arg); result = __fcntl64(fd, mips_cmd, (void *)flags); break; case F_GETFL: result = __fcntl64(fd, mips_cmd, arg); if (result != -1) result = fcntl_flags_ntop(result); break; case F_DUPFD: case F_GETFD: case F_SETFD: case F_SETOWN: case F_GETOWN: case F_SETSIG: case F_GETSIG: case F_SETLEASE: case F_GETLEASE: case F_NOTIFY: ALOGV("%s: Calling __fcntl64(fd:%d, mips_cmd:0x%x, arg:%p);", __func__, fd, mips_cmd, arg); result = __fcntl64(fd, mips_cmd, arg); if (result < 0) { ALOGV("%s: result = %d = __fcntl64(fd:%d, mips_cmd:0x%x, arg:%p);", __func__, result, fd, mips_cmd, arg); } else { if (mips_cmd == F_SETFD) { /* * File descriptor flag bits got set or cleared. */ flags = (int)arg; if (flags & FD_CLOEXEC) { filefd_CLOEXEC_enabled(fd); } else { filefd_CLOEXEC_disabled(fd); } } } break; default: /* * This is likely a rare situation, abort() would hang fcntl13 LTP test. */ ALOGE("%s: mips_cmd:%d doesn't appear to be supported;", __func__, mips_cmd); ALOGV("%s: Assume it doesn't need to be mapped!", __func__); result = __fcntl64(fd, mips_cmd, arg); } done: ALOGV("%s: return(result:%d); }", __func__, result); return result; }
/// \par parameters: expression dest, to be dereferenced under given guard, /// and given mode /// \return returns pointer after dereferencing exprt value_set_dereferencet::dereference( const exprt &pointer, const guardt &guard, const modet mode) { if(pointer.type().id()!=ID_pointer) throw "dereference expected pointer type, but got "+ pointer.type().pretty(); // we may get ifs due to recursive calls if(pointer.id()==ID_if) { const if_exprt &if_expr=to_if_expr(pointer); // push down the if guardt true_guard=guard; guardt false_guard=guard; true_guard.add(if_expr.cond()); false_guard.add(not_exprt(if_expr.cond())); exprt true_case=dereference(if_expr.true_case(), true_guard, mode); exprt false_case=dereference(if_expr.false_case(), false_guard, mode); return if_exprt(if_expr.cond(), true_case, false_case); } // type of the object const typet &type=pointer.type().subtype(); #if 0 std::cout << "DEREF: " << from_expr(ns, "", pointer) << '\n'; #endif // collect objects the pointer may point to value_setst::valuest points_to_set; dereference_callback.get_value_set(pointer, points_to_set); #if 0 for(value_setst::valuest::const_iterator it=points_to_set.begin(); it!=points_to_set.end(); it++) std::cout << "P: " << from_expr(ns, "", *it) << '\n'; #endif // get the values of these std::list<valuet> values; for(value_setst::valuest::const_iterator it=points_to_set.begin(); it!=points_to_set.end(); it++) { valuet value=build_reference_to(*it, mode, pointer, guard); #if 0 std::cout << "V: " << from_expr(ns, "", value.pointer_guard) << " --> "; std::cout << from_expr(ns, "", value.value) << '\n'; #endif values.push_back(value); } // can this fail? bool may_fail; if(values.empty()) { invalid_pointer(pointer, guard); may_fail=true; } else { may_fail=false; for(std::list<valuet>::const_iterator it=values.begin(); it!=values.end(); it++) if(it->value.is_nil()) may_fail=true; } if(may_fail) { // first see if we have a "failed object" for this pointer const symbolt *failed_symbol; exprt failure_value; if(dereference_callback.has_failed_symbol( pointer, failed_symbol)) { // yes! failure_value=failed_symbol->symbol_expr(); failure_value.set(ID_C_invalid_object, true); } else { // else: produce new symbol symbolt symbol; symbol.name="symex::invalid_object"+std::to_string(invalid_counter++); symbol.base_name="invalid_object"; symbol.type=type; // make it a lvalue, so we can assign to it symbol.is_lvalue=true; get_new_name(symbol, ns); failure_value=symbol.symbol_expr(); failure_value.set(ID_C_invalid_object, true); new_symbol_table.move(symbol); } valuet value; value.value=failure_value; value.pointer_guard=true_exprt(); values.push_front(value); } // now build big case split, but we only do "good" objects exprt value=nil_exprt(); for(std::list<valuet>::const_iterator it=values.begin(); it!=values.end(); it++) { if(it->value.is_not_nil()) { if(value.is_nil()) // first? value=it->value; else value=if_exprt(it->pointer_guard, it->value, value); } } #if 0 std::cout << "R: " << from_expr(ns, "", value) << "\n\n"; #endif return value; }
value_set_dereferencet::valuet value_set_dereferencet::build_reference_to( const exprt &what, const modet mode, const exprt &pointer_expr, const guardt &guard) { const typet &dereference_type= ns.follow(pointer_expr.type()).subtype(); if(what.id()==ID_unknown || what.id()==ID_invalid) { invalid_pointer(pointer_expr, guard); return valuet(); } if(what.id()!=ID_object_descriptor) throw "unknown points-to: "+what.id_string(); const object_descriptor_exprt &o=to_object_descriptor_expr(what); const exprt &root_object=o.root_object(); const exprt &object=o.object(); #if 0 std::cout << "O: " << from_expr(ns, "", root_object) << '\n'; #endif valuet result; if(root_object.id()=="NULL-object") { if(options.get_bool_option("pointer-check")) { guardt tmp_guard(guard); if(o.offset().is_zero()) { tmp_guard.add(null_pointer(pointer_expr)); dereference_callback.dereference_failure( "pointer dereference", "NULL pointer", tmp_guard); } else { tmp_guard.add(null_object(pointer_expr)); dereference_callback.dereference_failure( "pointer dereference", "NULL plus offset pointer", tmp_guard); } } } else if(root_object.id()==ID_dynamic_object) { // const dynamic_object_exprt &dynamic_object= // to_dynamic_object_expr(root_object); // the object produced by malloc exprt malloc_object= ns.lookup(CPROVER_PREFIX "malloc_object").symbol_expr(); exprt is_malloc_object=same_object(pointer_expr, malloc_object); // constraint that it actually is a dynamic object exprt dynamic_object_expr(ID_dynamic_object, bool_typet()); dynamic_object_expr.copy_to_operands(pointer_expr); // this is also our guard result.pointer_guard=dynamic_object_expr; // can't remove here, turn into *p result.value=dereference_exprt(pointer_expr, dereference_type); if(options.get_bool_option("pointer-check")) { // if(!dynamic_object.valid().is_true()) { // check if it is still alive guardt tmp_guard(guard); tmp_guard.add(deallocated(pointer_expr, ns)); dereference_callback.dereference_failure( "pointer dereference", "dynamic object deallocated", tmp_guard); } if(options.get_bool_option("bounds-check")) { if(!o.offset().is_zero()) { // check lower bound guardt tmp_guard(guard); tmp_guard.add(is_malloc_object); tmp_guard.add( dynamic_object_lower_bound( pointer_expr, ns, nil_exprt())); dereference_callback.dereference_failure( "pointer dereference", "dynamic object lower bound", tmp_guard); } { // check upper bound // we check SAME_OBJECT(__CPROVER_malloc_object, p) && // POINTER_OFFSET(p)+size>__CPROVER_malloc_size guardt tmp_guard(guard); tmp_guard.add(is_malloc_object); tmp_guard.add( dynamic_object_upper_bound( pointer_expr, dereference_type, ns, size_of_expr(dereference_type, ns))); dereference_callback.dereference_failure( "pointer dereference", "dynamic object upper bound", tmp_guard); } } } } else if(root_object.id()==ID_integer_address) { // This is stuff like *((char *)5). // This is turned into an access to __CPROVER_memory[...]. if(language_mode==ID_java) { result.value=nil_exprt(); return result; } const symbolt &memory_symbol=ns.lookup(CPROVER_PREFIX "memory"); exprt symbol_expr=symbol_exprt(memory_symbol.name, memory_symbol.type); if(base_type_eq( ns.follow(memory_symbol.type).subtype(), dereference_type, ns)) { // Types match already, what a coincidence! // We can use an index expression. exprt index_expr=index_exprt(symbol_expr, pointer_offset(pointer_expr)); index_expr.type()=ns.follow(memory_symbol.type).subtype(); result.value=index_expr; } else if(dereference_type_compare( ns.follow(memory_symbol.type).subtype(), dereference_type)) { exprt index_expr=index_exprt(symbol_expr, pointer_offset(pointer_expr)); index_expr.type()=ns.follow(memory_symbol.type).subtype(); result.value=typecast_exprt(index_expr, dereference_type); } else { // We need to use byte_extract. // Won't do this without a commitment to an endianness. if(config.ansi_c.endianness==configt::ansi_ct::endiannesst::NO_ENDIANNESS) { } else { exprt byte_extract(byte_extract_id(), dereference_type); byte_extract.copy_to_operands( symbol_expr, pointer_offset(pointer_expr)); result.value=byte_extract; } } } else { // something generic -- really has to be a symbol address_of_exprt object_pointer(object); if(o.offset().is_zero()) { equal_exprt equality(pointer_expr, object_pointer); if(ns.follow(equality.lhs().type())!=ns.follow(equality.rhs().type())) equality.lhs().make_typecast(equality.rhs().type()); result.pointer_guard=equality; } else { result.pointer_guard=same_object(pointer_expr, object_pointer); } guardt tmp_guard(guard); tmp_guard.add(result.pointer_guard); valid_check(object, tmp_guard, mode); const typet &object_type=ns.follow(object.type()); const exprt &root_object=o.root_object(); const typet &root_object_type=ns.follow(root_object.type()); exprt root_object_subexpression=root_object; if(dereference_type_compare(object_type, dereference_type) && o.offset().is_zero()) { // The simplest case: types match, and offset is zero! // This is great, we are almost done. result.value=object; if(object_type!=ns.follow(dereference_type)) result.value.make_typecast(dereference_type); } else if(root_object_type.id()==ID_array && dereference_type_compare( root_object_type.subtype(), dereference_type)) { // We have an array with a subtype that matches // the dereferencing type. // We will require well-alignedness! exprt offset; // this should work as the object is essentially the root object if(o.offset().is_constant()) offset=o.offset(); else offset=pointer_offset(pointer_expr); exprt adjusted_offset; // are we doing a byte? mp_integer element_size= dereference_type.id()==ID_empty? pointer_offset_size(char_type(), ns): pointer_offset_size(dereference_type, ns); if(element_size==1) { // no need to adjust offset adjusted_offset=offset; } else if(element_size<=0) { throw "unknown or invalid type size of:\n"+dereference_type.pretty(); } else { exprt element_size_expr= from_integer(element_size, offset.type()); adjusted_offset=binary_exprt( offset, ID_div, element_size_expr, offset.type()); // TODO: need to assert well-alignedness } index_exprt index_expr= index_exprt(root_object, adjusted_offset, root_object_type.subtype()); bounds_check(index_expr, tmp_guard); result.value=index_expr; if(ns.follow(result.value.type())!=ns.follow(dereference_type)) result.value.make_typecast(dereference_type); } else if(get_subexpression_at_offset( root_object_subexpression, o.offset(), dereference_type, ns)) { // Successfully found a member, array index, or combination thereof // that matches the desired type and offset: result.value=root_object_subexpression; } else { // we extract something from the root object result.value=o.root_object(); // this is relative to the root object const exprt offset=pointer_offset(pointer_expr); if(memory_model(result.value, dereference_type, tmp_guard, offset)) { // ok, done } else { if(options.get_bool_option("pointer-check")) { std::string msg="memory model not applicable (got `"; msg+=from_type(ns, "", result.value.type()); msg+="', expected `"; msg+=from_type(ns, "", dereference_type); msg+="')"; dereference_callback.dereference_failure( "pointer dereference", msg, tmp_guard); } return valuet(); // give up, no way that this is ok } } } return result; }