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