On 21.04.14 19:01, Bob Beck wrote:

> Not quite, because now you avoid the potential double free and instead leak
> ret itself because of how ASN1_STRING_free works.. You need to
> do this slightly differently.

I disagree:

err:
        if ((ret != NULL) && ((a == NULL) || (*a != ret)))
                ASN1_STRING_free(ret);

clearly, ret is not NULL and in order to have a ASN1_STRING we need to
free, the if ((a == NULL) || ((*a) == NULL)) on top must have triggered.
So indeed ASN1_STRING_free is called with

The ASN1_STRING_free function itself is rather straight forward:

void
ASN1_STRING_free(ASN1_STRING *a)
{
        if (a == NULL)
                return;
        if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
                free(a->data);
        free(a);
}

IOW: it only does abort early and thus not free() ret, if ret was NULL,
which is not the case once we get here. It will then free() ret->data if
it is not NULL (the double free case I wanted to solve) and then goes on
to free() ret.

Maybe I have missed the magic where a NULL data field in ASN1_STRING
makes ASN1_STRING_free not free the object, but I can't find that, at
least not in my source tree.

  erdgeist

Reply via email to