(冗長で申し訳ありません) OS X 10.6 (Snow Leopard) 用の Objective C で記述された Cocoa アプリケーションに OpenSSL サポートを追加する実験を行っています。簡単にするために、さまざまな BIO および暗号化コンテキスト構造を保持する小さなラッパー クラス AETOpenSSLWrapper を用意しました。次のようになります
.h
@interface AETOpenSSLWrapper: public NSObject
{
BIO *writeBIO,encBIO;
EVP_CIPHER_CTX *ctx;
unsigned char *readWriteBuff;
}
@property (readwrite,assign) BIO *writeBIO,*encBIO;
@property (readwrite,assign) EVP_CIPHER_CTX *ctx;
@property (readwrite,assign) unsigned char *readWriteBuff;
-(id)init;
...
-(void)dealloc;
@end
.m
@implementation AETOpenSSLWrapper
@synthesize writeBIO,encBIO,ctx,readWriteBuff;
-(id)init
{
self=[super init];
if(self)
{
writeBIO=BIO_new(BIO_s_file());
encBIO=...
ctx=...
buff=...
(error handling omitted)
}
return self;
}
@end
次に、BIO のチェーン、出力 BIO への書き込み、フラッシュなどを行うためのさまざまなユーティリティ メソッド、特に -(void)pushEncryptingBIO を使用して、暗号化フィルター BIO (キー、ソルト、および初期ベクトルで初期化されています) をチェーンします。
-(void)pushEncryptingBIO
{
writeBIO=BIO_push(encBIO,writeBIO);
}
最後に私の dealloc ルーチンがあります。これは、openssl-1.0.1c ディストリビューションで提供されるencプログラムから直接持ち上げられます。
-(void)dealloc
{
if(readWriteBuff!=NULL)
OPENSSL_free(readWriteBuff);
if(writeBIO!=NULL)
BIO_free_all(writeBIO);
if(encBIO!=NULL) <----------- this looks wrong
BIO_free(encBIO); <---+
[super dealloc];
}
同等のコードは、入力バッファーを暗号化するループの前、および openssl ソース ツリーの apps/enc.c の MAIN() ルーチンの最後にあります。
657~658行目
if (benc != NULL)
wbio=BIO_push(benc,wbio);
および 682 ~ 688 行
end:
ERR_print_errors(bio_err);
if (strbuf != NULL) OPENSSL_free(strbuf);
if (buff != NULL) OPENSSL_free(buff);
if (in != NULL) BIO_free(in);
if (out != NULL) BIO_free_all(out);
if (benc != NULL) BIO_free(benc); <--- are we sure about this?
問題は (最終的に) です: BIO がチェーンにプッシュされて解放されるため、その呼び出しBIO_free(benc)
(または私のコード内) が存在する必要がありますか? の実装を見ると、BIO チェーンを下っていくだけで、ref カウントを減らして解放し、ポインターを NULL アウトしません。これはバグに違いないように見えますが、明らかに、SSL メンテナーがこれを見逃していると思いたくありません。通話をそのままにしておくと、時折クラッシュが発生します (10 分の 1)。そうしないとクラッシュしませんが、リークは望ましくありません。これは Apple Event Handler 内にあるため、デバッグはさらに複雑になります。助言がありますか?BIO_free(encBIO)
writeBIO/out
BIO_free_all
BIO_free_all
BIO_free(encBIO)