You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Infamously, our varinfos for dynamically allocated memory are created with void type, because at the point of malloc/etc. we don't yet know, which type the values assigned to it will have. This is only determined at the point of assignment.
This creates the need for a notorious pile of hacks, including but not limited to the following:
|Addr ({ vtype = TVoid_; _}asv, offs) whennot (Cilfacade.isCharType t) -> (* we had no information about the type (e.g. malloc), so we add it; ignore for casts to char* since they're special conversions (N1570 6.3.2.3.7) *)
Addr ({ v with vtype = t }, offs) (* HACK: equal varinfo with different type, causes inconsistencies down the line, when we again assume vtype being "right", but joining etc gives no consideration to which type version to keep *)
Calculating types of offsets of alloc variables fails (because you cannot have offsets on void values), so we have fallbacks like this:
letget_type_addr (v,o) =try type_offset v.vtype o withType_offset (t,_) -> t
letget_type=function
|Addr (x, o) -> get_type_addr (x, o)
|StrPtr_ -> charPtrType (* TODO Cil.charConstPtrType? *)
|NullPtr -> voidType
|UnknownPtr -> voidPtrType
get_type_addr ((alloc@...), Field(x, NoOffset)) gives void, which gets into Type_offset from v.vtype instead of making some kind of assumption and using the field's type instead. That is, the type of an address with offsets might be the type of the variable (without the offsets). This can only cause further mismatches between types and abstract values, yielding to other type lookups also failing.
It's somewhat of a miracle how all these hacks manage to wipe the problem under multiple layers of carpet and have anything reasonable come out for blobs.
Solution
The standard defines (N1570 6.5.6):
The effective type of an object for an access to its stored value is the declared type of the object, if any.1 If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value. If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one. For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.
Given that the C standard has the notion of effective type exactly to describe how dynamically allocated memory gets its type from a subsequent assignment, we should adopt the same notion into the analyzer to avoid all the weird hacks above. Blobs could simply have an extra field for the effective type and any offset type lookups should take the effective type into count on Blobs, instead of erroring and falling back to whatnot.
Problem
Infamously, our
varinfo
s for dynamically allocated memory are created withvoid
type, because at the point ofmalloc
/etc. we don't yet know, which type the values assigned to it will have. This is only determined at the point of assignment.This creates the need for a notorious pile of hacks, including but not limited to the following:
varinfo
with updated type (problem for nice implementation of Handle renaming of local variables in incremental analysis (AST) #731):analyzer/src/cdomains/valueDomain.ml
Lines 332 to 333 in 35f5b9e
void
values), so we have fallbacks like this:analyzer/src/analyses/base.ml
Lines 1141 to 1152 in 35f5b9e
There are other places with
TypeOfError
as well.analyzer/src/cdomains/lval.ml
Lines 257 to 263 in 35f5b9e
get_type_addr ((alloc@...), Field(x, NoOffset))
givesvoid
, which gets intoType_offset
fromv.vtype
instead of making some kind of assumption and using the field's type instead. That is, the type of an address with offsets might be the type of the variable (without the offsets). This can only cause further mismatches between types and abstract values, yielding to other type lookups also failing.It's somewhat of a miracle how all these hacks manage to wipe the problem under multiple layers of carpet and have anything reasonable come out for blobs.
Solution
The standard defines (N1570 6.5.6):
Given that the C standard has the notion of effective type exactly to describe how dynamically allocated memory gets its type from a subsequent assignment, we should adopt the same notion into the analyzer to avoid all the weird hacks above. Blobs could simply have an extra field for the effective type and any offset type lookups should take the effective type into count on Blobs, instead of erroring and falling back to whatnot.
Footnotes
Allocated objects have no declared type. ↩
The text was updated successfully, but these errors were encountered: