Is there an equivalent to __attribute__((ns_returns_retained)) for a malloc'd pointer?

c, clang, objective-c, static-analysis

Solution

The function annotation `ownership_returns(malloc)` will tell the Clang static analyser that the function returns a pointer that should be passed to `free()` at some point (or a function with `ownership_takes(malloc, ...)`). For example:

void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
void __attribute((ownership_takes(malloc, 1))) my_free(void *);
...
void af1() {
    int *p = my_malloc(1);
    return; // expected-warning{{Potential leak of memory pointed to by}}
}
void af2() {
    int *p = my_malloc(1);
    my_free(p);
    return; // no-warning
}

(See the `malloc-annotations.c` test file for some more examples of their use.)

At the moment, these annotations only take effect when the `alpha.unix.MallocWithAnnotations` checker is run (which is not run by default). If you're using Xcode, you'll need to add `-Xclang -analyzer-checker=alpha.unix.MallocWithAnnotations` to your build flags.

Problem

I'm looking for an annotation something like ``` -(SomeStruct *) structFromInternals __attribute__((returns_malloced_ptr)) { SomeStruct *ret = malloc(sizeof(SomeStruct)); //do stuff return ret; } ``` to soothe the clang static analyzer beasts. The only viable attributes link I can find is for GCC, but it doesn't even include `ns_returns_retained`, which is in an extension, I assume. EDIT: as to why this is needed, I have a scenario that I can't repro in a simple case, so it may have to do with a c lib in an Objective-C project... The gist is, I get a static analyzer warning that the malloc in createStruct is leaked: ``` typedef struct{ void * data; size_t len; }MyStruct; void destroyStruct(MyStruct * s) { if (s && s->data) { free(s->data); } if (s) { free(s); } } MyStruct * createStructNoCopy(size_t len, void * data) { MyStruct * retStruct = malloc(sizeof(MyStruct)); retStruct->len = len; retStruct->data = data; return retStruct; } MyStruct * createStruct(size_t len, void * data) { char * tmpData = malloc(len); memcpy(tmpData, data, len); return createStructNoCopy(len, tmpData); } MyStruct * copyStruct(MyStruct * s) { return createStruct(s->len, s->data); } ```

Original source