1

私の(ココア)-Xcode内から起動すると、アプリは完全に正常に動作します。ただし、アーカイブ/リリースすると、そのバージョンがクラッシュします。開いたエラーレポーターは次のように述べています。

[...]    
Crashed Thread:  0  Dispatch queue: com.apple.main-thread

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000

Application Specific Information:
[9082] stack overflow

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib          0x00007fff944a7212 __pthread_kill + 10
1   libsystem_c.dylib               0x00007fff9290caf4 pthread_kill + 90
2   libsystem_c.dylib               0x00007fff92950e9e __abort + 159
3   libsystem_c.dylib               0x00007fff92951d17 __stack_chk_fail + 195
[...] 

また、実行が停止したコード行も表示されますが、まったく同じコードパスがデバッグモードで実行されるため(ただし成功するため)、これは実際には役に立ちません。

だから私は疑問に思っています:実際には、リリースとデバッグバージョンでスタックサイズが異なるのでしょうか?そして、結局のところMac(64ビット/ Mountain Lion)のスタックはどれくらいの大きさですか?スタックにめちゃくちゃ多くのデータを入れていることに気づいていません...

スタックにデータが多すぎる場合、スタックの負荷を減らすためにどのようなパターンを避ける必要がありますか?

[アップデート]

わかりました-fno-stack-protector。フラグを追加してアプリを実行しました。(ところで:私はLLVMでコンパイルしています)

その前に、クラッシュするコードを1行ずつ調べてみたところ、理解できない次の動作が見つかりました。メソッドは。をfoo(x)呼び出しますbacon(x)xは8で、変更なしでからfooに渡されbaconます。しかし、私が足を踏み入れるとbacon(x)x突然4295939448になります(毎回)。私が設定した場合-fno-stack-protector、値は正しいです。

私の素朴な目には、これはスタックプロテクターがスタックのどこかに魔法の値4295939448を設定し、それを読み取り専用にするように見えます。そして、私の関数はパラメーターをスタックに置きますが、ある時点でパラメーターxがその魔法のアドレスに置かれるため、書き込むことができません(後続のパラメーターは正しく書き込まれているようです)。私の場合xはバッファ長パラメータであり、これは当然バッファオーバーフローとクラッシュにつながります。

誰かがスタックプロテクターをより深く理解していますか?なぜこうなった?また、スタックプロテクターを無効にすることはどのような場合に安全かつ合法であり、どのような場合に危険ですか?

[更新2:元のコード]

このメソッドは、Decrypt以下の他のメソッドを呼び出します。その時点でのstIVLenは8です

BOOL CEracomSE::Decrypt(
PBYTE pMsg, size_t stLen,
const CSK* pKey /* = NULL */,
PBYTE pIV /* = NULL */, size_t stIVLen /* = 0 */,
FBM fbm /* = FBM_CBC */,
PADDING padding /* = NO_PADDING */
)
{
    //stIVLen == 8
    return Decrypt( (uint64_t)0, pMsg, stLen, pKey, pIV, stIVLen, fbm, padding ); 
}

DecryptstIVLenが4295939448と呼ばれる場合、他のパラメーターは引き続き正しい

BOOL CEracomSE::Decrypt(
    uint64_t qwOffset, 
    PBYTE pMsg, size_t stLen,
    const CSK* pKey /* = NULL */,
    PBYTE pIV /* = NULL */, size_t stIVLen /* = 0 */,
    FBM fbm /* = FBM_CBC */,
    PADDING padding /* = NO_PADDING */
    )
{
    //stIVLen now is 4295939448
    BYTE a_iv[16] = {0};
    size_t a_iv_len;
    BYTE a_key[32] = {0};
    size_t a_key_len = 0;
    size_t nBytes;
    size_t nDataOffset;
    size_t nRemainingData = stLen;
    bool ret;
    //[...]
}
4

1 に答える 1

1

最近、アプリでこの状況に直面しました。私はそれが古いスレッドであることを知っていますが、他の誰かが調査結果から利益を得ることができるという意図でとにかく応答します.

質問で示唆されているように、渡す-fno-stack-protectorことで問題は解決しました。しかし、もう少し掘り下げてみると、すべてのリテラル配列宣言をより長い宣言に変更すると、コンパイラ フラグを渡さずに問題が解決することがわかりました。

そのため、すべての出現を変更します

@[@(1), @(2)]

[NSArray arrayWithObjects:@(1), @(2), nil]

私たちのアプリだけに固有のものかもしれませんが、他の人にも役立つことを願っています.

于 2014-09-05T08:22:33.387 に答える