[cfe-dev] Ownership attribute for malloc etc. checking

Jordy Rose jediknil at belkadan.com
Mon Jun 28 18:03:34 PDT 2010


A few last comments (along with what Ted had to say). Also, I second being
able to put the attributes on the arguments themselves. (Why didn't the GCC
people do nonnull like that?)


>> Here's the dispatch from EvalCallExpr(). I think even though it's
>> technically a little less efficient, you should just simplify this and
>> use
>> FD->getAttr<OwnershipTakesAttr>(), etc. It's a little simpler, and it
>> lets
>> you order the attributes.
>>
> 
> However, I did it this way because I wanted to allow two or more
attributes
> of the same kind (for the benefit of macros).
> 
> In other words, __attribute((ownership_holds, 1))
> __attribute((ownership_holds, 2)) should be the same
> as __attribute((ownership_holds, 1, 2)).
> 

Ah, good point. Okay, as long as return values are still handled (see
below).


>> Why does that matter? Because an ownership_takes() or ownership_holds()
>> function might have a return value! If it's also ownership_returns(),
>> then
>> you're fine, but otherwise you need to set a symbolic return value.
(You
>> can see how this is done in MallocMemAux(), or in StreamChecker.cpp
with
>> fopen.) There should probably be a test for this as well.
> 
> 
> It isn't necessarily the case that an ownership_takes() function that
> returns a pointer generated that pointer from an ownership_takes
argument,
> or allocated anything, so what would you set the region to, in the
absence
> of other information?  They default to Unknown, yes?

I believe so, but for return values from function calls we prefer to use a
"conjured symbol value". This is a kind of value that can be reasoned about
symbolically in later statements -- for example, we can bound its value if
it's an integer, or mark that it's null or non-null if it's a pointer.


>> What does it mean to have multiple size fields? There can still only be
>> one return value. Maybe you should only allow zero or one positions for
>> ownership_returns (which would make this section simpler).
>>
> 
> The intention here was to implement something for calloc-like functions
and
> matrix allocators; one argument is a special case, more than one the
size
> of
> the region is the product of the arguments times sizeof(pointee of the
> return value), taking sizeof(void) as 1.  If it isn't worth doing that,
> fair
> enough, but that's what I was thinking this could lead to.

It's a good idea, but consider the following examples:

Node *getNode (size_t extra) {
  return malloc(sizeof(Node)+extra);
}

Node *getNode (size_t total) {
  assert(total >= extra);
  return malloc(total);
}

Node *getNodes (size_t count) {
  return malloc(sizeof(Node)*count);
}

Your proposal is to use the second or third meaning, based on whether one
or more arguments are included. I think we should just pick one meaning and
stick with it (i.e. not special-case the one-argument case). Or just take
it out, though as long as we allow the zero-argument case it doesn't hurt
anyone to handle arguments in one particular way.

> However, the parser only allows the one argument at the moment, so this
is
> redundant.



More information about the cfe-dev mailing list