Nice work! That sure looks like a bug to me, and it's not fixed in CVS.
 
If you make the change you suggest, does it plug your leak? If so, I'd file a bug to make sure it gets attention.


From: Cullum, Steve [mailto:[EMAIL PROTECTED]
Sent: Thursday, October 13, 2005 8:39 AM
To: [email protected]
Subject: RE: why would this code fragment cause XSec1.2.0 to leak memory?

I think this may be the problem..inside the destructor
~WinCAPICryptoKeyRSA::CryptDestroyKey() never gets called. 
 
I this is already fixed in the CVS release...sorry!!! to waste your time
 
WinCAPICryptoKeyRSA::~WinCAPICryptoKeyRSA()
{
    // If we have a RSA, delete it
    if (m_key == 0)
        CryptDestroyKey(m_key);
/**
 ** Shouldnt this be
 
    if (m_key != 0)
        CryptDestroyKey(m_key);
 **
 **/
 
    if (mp_exponent)
      delete[] mp_exponent;
 
    if (mp_modulus)
      delete[] mp_modulus;
};
 
 
 

From: Cullum, Steve [mailto:[EMAIL PROTECTED]
Sent: 13 October 2005 13:01
To: [email protected]
Subject: RE: why would this code fragment cause XSec1.2.0 to leak memory?

Okay.. my memory leak seems to occur as soon as i call X509->clonePublicKey().
 
Calling prov->releaseSignature(sig) does not seem to release memory for the key.
 
The entire test driver that recreates the memory leak is shown.. I am basically doing what the documentations except i call the signature validation in a loop.
 
While(1)
{
    XercesDOMParser parser;
    parser.setDoNamespaces(true);
    parser.setCreateEntityReferenceNodes(true);
    parser.setDoSchema(true);
 
    MemBufInputSource *memIS = new MemBufInputSource((const XMLByte *)buffer, bufferLen,    "XSECMem", false);
     
    parser.parse(*memIS);
    delete memIS;                               // destroy as soon as possible
    
    // Now create a signature object to validate the document
    XSECProvider prov;
    DSIGSignature *sig = prov.newSignatureFromDOM(parser.getDocument());
 
    sig->registerIdAttributeName(config.idAttributeName);
    sig->registerIdAttributeNameNS(config.idAttributeNS, config.idAttributeName);
    sig->load(); 
    sig->setSigningKey(X509->clonePublicKey());        // memory just goes up.. and up.. when i clone a key 
    sig->verify();
    prov->releaseSignature(sig);
}
 
 



From: Cullum, Steve [mailto:[EMAIL PROTECTED]
Sent: 12 October 2005 17:08
To: [email protected]
Subject: RE: why would this code fragment cause XSec1.2.0 to leak memory?

Thanks Jesse, i have run this under a release and debug build and nothing is indicated.  I know its in this code fragmant, as my application can run for hours on end with no memory issues. 
 
Turning on ValidateSig() causes a slow but sure memory increase.  AFAIK i have deleted/free'd all objects that xml-sec is using and still my memory usage increases.
 
Is there anything obviously amiss with this code fragment?  Am i calling fn()'s in the incorrect order, doing anything that could result in undefined behaviour etc.
 
 
    XercesDOMParser parser;
    parser.setDoNamespaces(true);
    parser.setCreateEntityReferenceNodes(true);
    parser.setDoSchema(true);
 
    MemBufInputSource *memIS = new MemBufInputSource((const XMLByte *)buffer, bufferLen,    "XSECMem", false);
     
    parser.parse(*memIS);
    delete memIS;                               // destroy as soon as possible
    
    // Now create a signature object to validate the document
    XSECProvider prov;
    DSIGSignature *sig = prov.newSignatureFromDOM(parser.getDocument());
 
    sig->registerIdAttributeName(config.idAttributeName);
    sig->registerIdAttributeNameNS(config.idAttributeNS, config.idAttributeName);
    sig->load(); 
    sig->setSigningKey(X509->clonePublicKey());
    sig->verify();
    prov->releaseSignature(sig);
 
 


From: Jesse Pelton [mailto:[EMAIL PROTECTED]
Sent: 12 October 2005 16:44
To: [email protected]
Subject: RE: why would this code fragment cause XSec1.2.0 to leak memory?

Have you tried running a debug build of your code under the debugger? After the program terminates, you may find memory leaks listed in the output window. Sometimes there's enough information to make it obvious where the leak is, sometimes not. (It's a good idea to do this in the course of development; it's much easier to locate the problem if you know it's in code you're working on.)


From: Cullum, Steve [mailto:[EMAIL PROTECTED]
Sent: Wednesday, October 12, 2005 11:07 AM
To: [email protected]
Subject: why would this code fragment cause XSec1.2.0 to leak memory?

Can someone please help me or point me in the right direction. When running my application memory usage increases slowly by about 6mb / hour.  Commenting out the function digital signature validation routing ValidateSig() stops the memory increase.
 
a) I am getting no errors, so the leak can is not inside my "catch" constructs.  
b) I am using the MS Crypto api .. (is that relevant??)
c) I am linking to xerces-c_2_6.dll [release] and xsec_1_2_0.dll [release] with no XALAN support on Windows 2003 compiled with VS2003.net
 
I have looked up & down this source and can see no obvious mistakes! 
 
Can anyone help me please?
 
 
 
 
 
BOOL ValidateSig()
{

  //
  // parse the XML document, load in the signature field and attempt to validate it using a copy of the
  // X509 public key we create earlier from the certificate store.
  //
  BOOL valid = FALSE;
  try
  {
    XercesDOMParser parser;
    parser.setDoNamespaces(true);
    parser.setCreateEntityReferenceNodes(true);
    parser.setDoSchema(true);
 
    MemBufInputSource *memIS = new MemBufInputSource((const XMLByte *)buffer, bufferLen, "XSECMem", false);
     
    parser.parse(*memIS);
    delete memIS;                               // destroy as soon as possible
    if(parser.getErrorCount() > 0)
    {
      Display( "Error parsing input document", "error in XML parse", buffer, bufferLen) );
      return FALSE;
    }
 
    // Now create a signature object to validate the document
    XSECProvider prov;
    DSIGSignature *sig = prov.newSignatureFromDOM(parser.getDocument());
 
    sig->registerIdAttributeName(config.idAttributeName);
    sig->registerIdAttributeNameNS(config.idAttributeNS, config.idAttributeName);
    sig->load(); 
    sig->setSigningKey(X509->clonePublicKey());
    if(sig->verify())
    {
      Display(_T("Signature Valid...OK"));
      valid = TRUE;  // the only way to set this is if this fn() is successfull
    }
    else
    {
      char *err = XMLString::transcode(sig->getErrMsgs());
      Display("Error parsing [or] validating document", err, buffer, bufferLen);
      XSEC_RELEASE_XMLCH(err);
      Display("Error parsing [or] validating document\n%s", sig->getErrMsgs());
    }
 
    prov->releaseSignature(sig);
  }
  catch(XSECException &e) // signature related errors
  {
    char *err = XMLString::transcode(e.getMsg());
    Display( "An error occured during signature load", err, buffer, bufferLen);
    XSEC_RELEASE_XMLCH(err);
    Display(_T("An error occured during signature load\n%s", e.getMsg());  // e.getMsg() is WIDE
  }
  catch(const XMLException &e) // xml related parsing errors
  {
    char *err = XMLString::transcode(e.getMessage());
    Display("An error occured during xerces parsing and loading of xml", err, buffer, bufferLen);
    XSEC_RELEASE_XMLCH(err);
    Display( _T("An error occured during xerces parsing and loading of xml\n%s"), e.getMessage()); // e.getMessage() is WIDE
  }
 
  return valid;
}
 
 
// XSec startup code && x509 constuction.. dont think its relevant here.
 
SomeConstructor()
{
  // startup xerces & xsec for signature validation
  // because parts of the Apache signature library are not thread safe - all initialisation
  // now takes place inside the constructor - rather than the preferred Init() method.
  // i NEVER destroy the cryptoProv object... it is owned by XSEC and is killed vie XSECPlatformUtils::Terminate()
  //
  try
  {
    // initialize xerces xml parser and the Apache XML-Security library
    XMLPlatformUtils::Initialize();
    XSECPlatformUtils::Initialise(); 
 
    cryptoProv = new WinCAPICryptoProvider(NULL, NULL, 0);
    XSECPlatformUtils::SetCryptoProvider(cryptoProv);       // this is set "globally"
  }
  catch(const XMLException &e)
  {
    throw; // rethrow..to waiting handler
  }
}
 
BOOL CreateX509()
{
  //
  // load the public key from the certificate store. 
  // install the key as a service certificate using mmc->certificates->services certificate,
  // browse for the "microsoft firewall" and install the cert in the Trusted Root Authority.
  // For example the "microsoft firewall" uses the storeName L"fwsrv\Root"
  //
  HCERTSTORE     certStore = NULL;
  PCCERT_CONTEXT certContext = NULL;
  DWORD          certOpenFlags = CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_SERVICES | CERT_STORE_READONLY_FLAG;
 
  // open the store .. fail if the store does not exist, look in the services store, open for readonly
  certStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, certOpenFlags, config.storeName);
  if(certStore == NULL)
  {
    _com_error e(GetLastError());
    return FALSE;
  }
 
  // find signer's certificate
  certContext = CertFindCertificateInStore(certStore, (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), 0, CERT_FIND_SUBJECT_STR, config.signerName , NULL);
  CertCloseStore(certStore, 0); // close the store regardless
  if(certContext == NULL)
  { 
    _com_error e(GetLastError());
    return FALSE;
  }
 
  try
  {
    if(X509 != NULL)  // if we have already been created .. then destroy and re-create
      delete X509;    // X509 destructor takes care of CertFreeCertificateContext()
    X509 = new WinCAPICryptoX509(certContext, cryptoProv->getProviderRSA(), cryptoProv->getProviderDSS());
  }
  catch(XSECCryptoException &e)
  {
    delete X509;
    return FALSE;
  }
 
  return TRUE;
}
 
 

Reply via email to