範囲外のビットシフト

範囲外のビットシフト

説明

JavaScriptのNumberに対するビットシフトは32ビット整数として演算し、右オペランドの下位5ビットだけを使います。そのため、32以上や負のシフト数では意図した算術結果と異なることがあります。これは計算の正確性の問題であり、セキュリティへの影響は、その結果を権限やリソースの処理にどう使うかによります。

想定される影響

  • ビットマスクやフラグが意図と異なる値になる可能性があります。
  • 長さ、サイズ、インデックスの計算誤りから、不適切なリソース処理につながるおそれがあります。
  • 64ビット以上の整数を想定した計算が、32ビットのシフト規則で処理される可能性があります。

対処方法

  • Numberのシフト数を0から31に制限してください。
  • 32ビットを超える整数演算にはBigIntを使い、範囲も明示的に確認してください。
  • マスクやサイズ計算の定数が意図した結果になることをテストしてください。

例

変更前

javascript
const ADMIN_MASK = 1 << 32;

function hasAdmin(flags) {
  return (flags & ADMIN_MASK) !== 0;
}

変更後

javascript
const ADMIN_MASK = 1n << 32n;

function hasAdmin(flags) {
  return (BigInt(flags) & ADMIN_MASK) !== 0n;
}

1 << 32は意図した33番目のビットではなく、1 << 0と同じ1になります。変更後はBigIntでそのビット位置を計算します。大きな値を先にNumberへ変換すると精度が失われるため、flagsは正確な整数文字列かBigIntとして渡し、形式と許容範囲を検証してください。

参考資料