13

Fortify は、これが範囲外の読み取りであることを示します。

if (strncmp("test string", "less than 32 char", 32) == 0)
{
...
}

関数は の境界外からデータを読み取ると書かれていますless than 32 char

strncmpが32 文字を超え、2 番目の文字列が 32 文字未満の場合、実際に結果は得られますか?

4

3 に答える 3

13

パフォーマンス上の理由から、標準の文字列関数の実装では、自然に整列されたレジスタ幅のチャンクでデータを処理することがよくあります。これにより、ソース データ オブジェクトの末尾を超えて読み取りアクセスが発生する可能性がありますが、アラインメントにより、コードがメモリ例外に関して単純な実装とまったく同じように動作することが保証されます。各ワイド アクセスは 1 つのページ内に含まれ、バイト単位の実装でも触れられないページには触れられません。

そのような実装は、C の as-if ルールによってカバーされている、つまり、抽象的な機能仕様に従っているかのように「あたかも」同じように動作すると主張します。

このような最適化された実装の例は、OpenSolaris のstrcmp()SPARC v8です。これは、パフォーマンスが最適化された他の文字列関数と共に、15 年ほど前に私が書いたコードです。

ただし、さまざまなメモリ チェッカー ツールは、このようなコードに対して問題を起こす可能性があります。これは、境界外の読み取りアクセスが設計上無害であっても、そのようなコードを使用すると、割り当てられたデータ オブジェクトの制限を超えてアクセスする可能性があるためです。

于 2016-08-10T19:56:54.260 に答える
10

TL;DR -文字列の末尾または 32 個の要素 (文字) のいずれか少ない方まで、文字列strncmp()要素の比較を続けます。

( ny )文字列は常に null で終了し、null ターミネータに遭遇すると、それ以上の比較は実行されません。あなたのコードは安全です。

引用C11、章§7.24.4.4(強調鉱山

int strncmp(const char *s1, const char *s2, size_t n);

このstrncmp関数は、 が指す配列と が指す配列とを比較します (ヌル文字に続く文字は比較されません)ns1s2

于 2016-08-10T15:54:16.777 に答える
6

完全に有効なコードがあります。

コンパイラが不正なオブジェクト コードを生成しているか、fortify が誤検知を報告しています。

コンパイラが悪いコードを生成しているとは思えません。これはあまりにも多くの問題を引き起こし、すぐに検出されて修正されます。

fortify が誤検知を報告している可能性が最も高いです。

于 2016-08-10T15:54:30.287 に答える