INT13-C. ビット単位の演算子は符号無しオペランドに対してのみ使用する
ビット単位の演算子には、補数演算子 ~
、ビット単位のシフト演算子 >>
および <<
、ビット単位の AND 演算子 &
、ビット単位の排他 OR 演算子 ^
およびビット単位の OR 演算子 |
がある。ビット単位の演算子は符号無し整数オペランドに対してのみ使用すること。符号付き整数に対して使用すると処理系定義の動作を引き起こす場合がある。
違反コード (右シフト)
右シフト演算は算術(signed)シフトあるいは論理(unsigned)シフトのいずれかで実装される。式 E1 >> E2
中の E1
が符号付きの型で負の値であるならば、結果の値は処理系定義である。また、ビット単位のシフト演算は未定義の動作となることがある。(「INT34-C. 負のビット数のシフトやオペランドのビット数以上のシフトを行わない」を参照。)
以下のコード例は、算術シフトが行われ、かつ符号ビットが伝播する処理系では、エラーとなることがある[Dowd 2006]。
int rc = 0; int stringify = 0x80000000; char buf[sizeof("256")]; rc = snprintf(buf, sizeof(buf), "%u", stringify >> 24); if (rc == -1 || rc >= sizeof(buf)) { /* エラー処理 */ }
この例では、stringify >> 24
が 0xFFFFFF80
(10進の 4,294,967,168) に評価される。文字列に変換すると、結果の値 "4294967168"
は buf
に格納するには大きすぎるため、snprintf()
によって切り捨てられる。
このコードが snprintf()
のかわりに sprintf()
を使って実装されていたなら、バッファオーバーフローにつながっていただろう。
適合コード (右シフト)
以下の適合コードでは、stringify
を unsigned
整数として宣言している。右シフト演算の結果の値は、stringify / 2^24
の商の整数部分である。
int rc = 0; unsigned int stringify = 0x80000000; char buf[sizeof("256")]; rc = snprintf(buf, sizeof(buf), "%u", stringify >> 24); if (rc == -1 || rc >= sizeof(buf)) { /* エラー処理 */ }
また、snprintf()
の代わりに ISO/IEC TR 24731-1 で定義されている関数 sprintf_s()
を使用してさらなるチェックを行うことを検討せよ。(「STR07-C. 境界チェックインタフェースを使用し、文字列操作を行う既存のコードの脅威を緩和する」を参照。)
例外
INT13-EX1: ビットフラグとして使用する場合は、値が明示的に符号無しとして宣言されていなくても、プリプロセッサマクロを &
および |
演算子の引数として使ってもよい。
fd = open(file_name, UO_WRONLY | UO_CREAT | UO_EXCL | UO_TRUNC, 0600);
INT13-EX2: シフト演算子の右オペランドがコンパイル時に決まっている場合、その値が正であるならば値を符号付き型で表現してもよい。
#define SHIFT 24 foo = 15u >> SHIFT;
リスク評価
ビット単位の演算子を符号付きの数に対して行うと、バッファオーバーフローや攻撃者による任意のコード実行につながったり、予期せぬあるいは処理系定義の動作につながるおそれがある。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
INT13-C |
高 |
低 |
中 |
P6 |
L2 |
自動検出
ツール |
バージョン |
チェッカー |
説明 |
---|---|---|---|
Compass/ROSE |
|
|
このルールの違反を検出できる。特に、 |
ECLAIR |
1.1 |
optrargs |
実装済み |
Fortify SCA |
5.0 |
|
CERT C Rule Packを使ってこのレコメンデーションの違反を検出できる |
LDRA tool suite |
V. 8.5.4 |
50 S |
実装済み |
PRQA QA-C | 8.1 |
0502 |
実装済み |
Splint |
V. 3.1.1 |
|
|
関連するガイドライン
CERT C++ Secure Coding Standard | INT13-CPP. Use bitwise operators only on unsigned operands |
ISO/IEC TR 24772:2013 | Bit Representations [STR] Arithmetic Wrap-around Error [FIF] Sign Extension Error [XZI] |
MITRE CWE | CWE-682, Incorrect calculation |
参考資料
[Dowd 2006] | Chapter 6, "C Language Issues" |
[ISO/IEC 2003] | Section 6.5.7, "Bitwise Shift Operators" |
翻訳元
これは以下のページを翻訳したものです。
INT13-C. Use bitwise operators only on unsigned operands (revision 75)