Thanks for the explanation and pinter for the relevant ASN1 function.

Erwin

--------------------------------------------------
From: "Jakob Bohm" <jb-open...@wisemo.com>
Sent: Friday, September 09, 2011 4:22 AM
To: <openssl-users@openssl.org>
Subject: Re: How to Check Whether the resources of X509 has been freed when it is freed by X509_free()

On 9/9/2011 5:21 AM, Erwin Himawan wrote:
Hi All,
I have several questions associated with freeing resources of X509 struct.
snippet of my code:
X509 *x509Cert = X509_new();
if (x509Cert == NULL) printf("Error instantiating X509 object\n");
/* do some processing with my x509Cert object */
/* Cleaning up resources of x509Cert */
if(x509Cert != NULL) X509_free(x509Cert);
My questions are:
1. How to check that x509Cert resources have been freed? I notice that
X509_free(x509Cert) does not set the x509Cert to NULL, therefore I can not
rely on if(x509Cert != NULL) to verify that x509Cert resources has been
freed. this a bug or there are other method for verifying whether x509Cert
resources have been freed.
As OpenSSL is a C (not C++ or Pascal) API, unless a function takes an
explicit pointer to your x509Cert variable it is not supposed to have the
ability to change it.  This is one of the nice semantic guarantees of the
C language.

As x509_free() returns void, you should simply assume that the call *will* free what it is told to free, to the maximum extent reasonably possible, which is actually the sanest and most programmer friendly way to specify a cleanup function (for the same reason, C++ destructors have no return value either and are barred from using exceptions during stack unwind). It is good practice to wrap it in a block such as the following: { X509 *ptmp = x509Cert; x509Cert = NULL; // Do this first to reduce risk of race conditions // in your own multithreading x509_free(tmp); } Or in C++ you could declare a macro-assisted smart pointer type similar to the following: (NOT TESTED!) (For C++ purists: the macros are used to do the name pasting needed to refer to individual per-type global function names and to generate obvious class names such as X509Ptr, all the real work is done by the C++ template).

#define ASNPTR_TYP(typ) ASNPtr<type, typ##_new, typ##_free> #define DECLARE_ASNPTR(typ) typedef ASNPTR_TYP(typ) typ##Ptr; class ASNPTRBase { protected: void *p; public: typedef ASNPTRBase Self; typedef Self* PSelf; typedef void *PTYP; protected: PTYP Take(void) { PTYP p1 = p; p = 0; return p1; } ASNPtrBase(): p(0) {} ASNPtrBase(PTYP p1) p(p1) {} ASNPTRBase(Self &p1) p(p1.Take()) {} ~ASNPTRBase() { } public: bool operator bool() const { return !!p; } PTYP operator PTYP() const { return p; } private: Self & operator = (PTYP p1) {}; // Not available, do not generate default impl. Self & operator = (Self &p1) {}; // Not available, do not generate default impl. }; template < class ASNT, ASNT* (*ASNT_new)(void), void (*ASNT_free)(ASNT *p) > class ASNPtr: public ASNPTRBase { public: typedef ASNPtr Self; typedef Self *PSelf; typedef ASNT * PTYP; PTYP Take(void) { return (PTYP)ASNPTRBase::Take(); } void Free(void) { // Must be in template because of type-specic specific call PTYP p1 = Take(); if (p1) ASNT_free(p1); } ASNPtr &Alloc(void) { // Must be in template to avoid adding a vptr to the size of ASNPtrBase objects Free(); p = ASNT_new(); } ASNPtr &Set(PTYP p1) { // Must be in template to avoid adding a vptr to the size of ASNPtrBase objects Free(); p = p1; } ASNPtr &Set(ASNPtr &p1) { return Set(p1.Take()); } ASNPtr() {} ASNPtr(PTYP p1) ASNPTRBase(p1) {} ASNPtr(ASNPtr&p1) ASNPtrBase(p1) {} ~ASNPtr() { Free(); } Self& operator = (PTYP p1) { return Set(p1); } Self& operator = (Self &p1) { return Set(p1); } PTYP operator PTYP() const { return p; } private: Self& operator = (const Self &p1) {} // Not available, do not generate default impl. // do not generate call to operator=(p1.operator PTYP()) // for const source objects as that would ruin the // rule that only one ASNPTR can own the object at // any given time. } DECLARE_ASNPTR(X509) DECLARE_ASNPTR(X509_NAME) DECLARE_ASNPTR(X509_CRL) // etc.


2. Does X509_free() also free all the internal objects that are part of the
X509 struct; e.g. X509_ALGOR, X509_NAME, ASN1_INTEGER, ASN1_TIME, etc
Thanks,
Erwin
Please look at the source code of the function ASN1_item_free, which does
the real work.


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager majord...@openssl.org

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to