Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   OpenSSL - MemoryLeak bei Verwendung eines X509-Zertifikats (https://www.delphipraxis.net/189896-openssl-memoryleak-bei-verwendung-eines-x509-zertifikats.html)

DeddyH 5. Aug 2016 13:02

OpenSSL - MemoryLeak bei Verwendung eines X509-Zertifikats
 
Ich muss mich aktuell mit digitaler Signierung herumschlagen. Dazu verwende ich OpenSSL (libeay32.dll). Die verwendeten Header-Übersetzungen habe ich von hier. Jetzt ist mir ein Speicherleck aufgefallen, das sich hartnäckig hält.
Delphi-Quellcode:
procedure TMyClass.Verfify;
var
  Certificate: TBytes;
  CertStr: PPAnsiChar;
  Cert: PX509;
begin
  //...
  CertStr := @PAnsiChar(Certificate);
  Cert := d2i_X509(nil, CertStr, TC_LONG(Length(Certificate)));
  if Assigned(Cert) then
    try
      //Auskommentierter Code
    finally
      X509_free(Cert);
    end;
end;
Laut Doku dekrementiert X509_free den internen Referenzzähler auf die X509-Struktur und gibt diese bei Erreichen von 0 frei. Leider scheint dem nicht so zu sein, also mache ich wohl irgendetwas falsch. Kommentiere ich den Teil ab d2i_X509 bis X509_free aus, ist das Speicherleck weg, es muss also damit zu tun haben. Hat jemand einen Tipp für mich, die Speicherverwaltung von OpenSSL ist für mich doch recht gewöhnungsbedürftig?

DeddyH 7. Aug 2016 10:04

AW: OpenSSL - MemoryLeak bei Verwendung eines X509-Zertifikats
 
Ein dezentes *Push* :oops:

DeddyH 8. Aug 2016 08:53

AW: OpenSSL - MemoryLeak bei Verwendung eines X509-Zertifikats
 
Ich konnte das Problem jetzt mildern, indem ich die PX509-Variable zu einem privaten Feld gemacht habe und dieses nur befülle, wenn noch nicht zugewiesen. Das Speicherleck besteht zwar weiterhin, aber es entspricht halt nur einmal der Größe der zugrundeliegenden Struktur und nicht einmal je Aufruf. Trotzdem hätte ich das gern ganz weg, bin also weiterhin dankbar für jeden Tipp.

Bambini 8. Aug 2016 09:02

AW: OpenSSL - MemoryLeak bei Verwendung eines X509-Zertifikats
 
Zitat:

Zitat von DeddyH (Beitrag 1344248)
Laut Doku dekrementiert X509_free den internen Referenzzähler auf die X509-Struktur und gibt diese bei Erreichen von 0 frei. Leider scheint dem nicht so zu sein, also mache ich wohl irgendetwas falsch. Kommentiere ich den Teil ab d2i_X509 bis X509_free aus, ist das Speicherleck weg, es muss also damit zu tun haben. Hat jemand einen Tipp für mich, die Speicherverwaltung von OpenSSL ist für mich doch recht gewöhnungsbedürftig?

Woran erkennst du den Memory Leak?
Das MM der DLL ist nicht der MM von Delphi. D.h. meldet der Delphi einen Leak, so hat den Speicher Delphi auch reserviert.

DeddyH 8. Aug 2016 09:11

AW: OpenSSL - MemoryLeak bei Verwendung eines X509-Zertifikats
 
Zum Einen wird es mir bei ReportMemoryLeaksOnShutdown gemeldet, zum Anderen kann ich im Taskmanager sehen, wie der Speicherverbrauch ansteigt.

Bambini 8. Aug 2016 09:20

AW: OpenSSL - MemoryLeak bei Verwendung eines X509-Zertifikats
 
Zitat:

Zitat von DeddyH (Beitrag 1344347)
Zum Einen wird es mir bei ReportMemoryLeaksOnShutdown gemeldet,

Dann stammt der Speicherbereich vom Delphi MM. D.h. der Speicher wurde von Delphi reserviert und nicht von der DLL.
Der Aufrufstack des FastMM zu den reservierenden Aufrufen, gibt dir Hinweise dazu.
Zitat:

Zitat von DeddyH (Beitrag 1344347)
zum Anderen kann ich im Taskmanager sehen, wie der Speicherverbrauch ansteigt.

Der sagt nur bedingt etwas aus und auch nicht ob es sich um einen Leak handelt.

Bbommel 28. Nov 2020 17:30

AW: OpenSSL - MemoryLeak bei Verwendung eines X509-Zertifikats
 
Ich muss mal diesen gut abgehangenen Thread ausgraben, auf den ich durch Google gestoßen bin. Ich habe gerade exakt das gleiche Problem, dass jeder Aufruf von d2i_x509 zu einem kleinen Speicherleck führt. Ziel bei mir ist es letztlich, ein in einem JSON Web Key angegebenes Zertifikat auszulesen und dann später im PEM-Format weiterzunutzen.

Kleiner Code-Auszug aus einem Testprogramm:

Delphi-Quellcode:
procedure TForm2.ButtonDecodeClick(Sender: TObject);

var
  byteArray: TBytes;
  pr: PX509;
  pubKey: string;
  bio: PBIO;

begin
  byteArray:=TNetEncoding.Base64.DecodeStringToBytes(MemoKey.Lines.Text);
  MemoStatus.Lines.Add('base decoded. Length: '+length(byteArray).ToString);
  if IdSSLOpenSSLHeaders.Load then begin
    MemoStatus.Lines.Add('openssl loaded.');
    pr:=d2i_X509(nil,@@byteArray[0],length(byteArray));
    if pr<>nil then begin
      MemoStatus.Lines.Add('X509 read.');
      MemoStatus.Lines.Add('Name: '+X509_NAME_oneline(X509_get_subject_name(pr),nil,0));
      MemoStatus.Lines.Add('Public Key Length: '+pr.cert_info.key.public_key.length.ToString);
      MemoStatus.Lines.Add('Issuer name: '+X509_NAME_oneline(X509_get_issuer_name(pr),nil,0));
      bio:=BIO_new(BIO_s_mem);
      PEM_write_bio_X509(bio,pr);
      BIO_read(bio,byteArray,BIo.num_write);
      pubKey:=string(PAnsiChar(@byteArray[0]));
      MemoPEM.Lines.Text:=pubKey;
      SetLength(bytePubKey,0);
      BIO_free(bio);
      X509_free(pr);
    end else
      MemoStatus.Lines.Add('Failed read X509.');

    SetLength(byteArray,0);
  end;
end;
Wie ihr seht, passiert hier noch etwas mehr (nämlich die Umwandlung in einen String im PEM-Format - falls jemand weiß, ob das einfacher geht, gerne her damit). Ich bin erstmal froh, dass am Ende das erhoffte Ergebnis rauskommt. :-)

Aber ich habe nun auch immer das Speicherleck. Ich kann den ganzen Code reduzieren zu

Delphi-Quellcode:
procedure TForm2.ButtonDecodeClick(Sender: TObject);

var
  byteArray, p: TBytes;
  pr: PX509;
  bytePubKey: TBytes;
  pubKey: string;
  bio: PBIO;

begin
  byteArray:=TNetEncoding.Base64.DecodeStringToBytes(MemoKey.Lines.Text);
  MemoStatus.Lines.Add('base decoded. Length: '+length(byteArray).ToString);
  if IdSSLOpenSSLHeaders.Load then begin
    MemoStatus.Lines.Add('openssl loaded.');
    pr:=d2i_X509(nil,@@byteArray[0],length(byteArray));
    if pr<>nil then
      X509_free(pr);
    else
      MemoStatus.Lines.Add('Failed read X509.');
    SetLength(byteArray,0);
  end;
end;
...und bekomme immer noch ein Speicherleck angezeigt.

Irgendwer vielleicht mittlerweile eine Idee? @DeddyH, hast du das damals gelöst bekommen oder nimmst du das Leck seitdem resigniert in Kauf?

hoika 28. Nov 2020 18:12

AW: OpenSSL - MemoryLeak bei Verwendung eines X509-Zertifikats
 
Hallo,
dein byteArray wird erzeugt, aber nur beim erfolgreichen Load per SetLength freigegeben.

Bbommel 28. Nov 2020 18:57

AW: OpenSSL - MemoryLeak bei Verwendung eines X509-Zertifikats
 
Zitat:

Zitat von hoika (Beitrag 1478125)
dein byteArray wird erzeugt, aber nur beim erfolgreichen Load per SetLength freigegeben.

Das stimmt natürlich und wäre prinzipiell auch eine Falle für ein Speicherleck, ist aber nur ein Fehler hier im Demoprojekt. Da die OpenSSL-Bibliothek bei mir immer geladen werden kann, ist das ByteArray auch immer freigegeben worden.

Leider ist das noch nicht die eigentliche Ursache.

Hm. Die Doku von OpenSSL gibt ja an, dass der Pointer auf das Array irgendwie verbogen wird und nachher hinter die übergebenen Byts zeigt. Irgendwie wird es wohl damit zusammenhängen. Man müsste sich also die ursprüngliche Adresse merken und sichergehen, dass man das richtige freigibt.

TiGü 28. Nov 2020 19:25

AW: OpenSSL - MemoryLeak bei Verwendung eines X509-Zertifikats
 
Zitat:

Zitat von Bbommel (Beitrag 1478128)
Man müsste sich also die ursprüngliche Adresse merken und sichergehen, dass man das richtige freigibt.

Wenn bloß einer geschrieben hätte, wie man das macht...
Zitat:

WARNINGS
The use of temporary variable is mandatory.
Du hast doch schon eine
Delphi-Quellcode:
p: TBytes
Variable in deiner Testfunktion drin. Nutze sie doch!


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:35 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz