ドライバーは、多くの場合、次の例のように、固定ヘッダーと末尾の可変長データを含む入力バッファーを受け入れます。
typedef struct _WAIT_FOR_BUFFER {
LARGE_INTEGER Timeout;
ULONG NameLength;
BOOLEAN TimeoutSpecified;
WCHAR Name[1];
} WAIT_FOR_BUFFER, *PWAIT_FOR_BUFFER;
if (InputBufferLength < sizeof(WAIT_FOR_BUFFER)) {
IoCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
return( STATUS_INVALID_PARAMETER );
}
WaitBuffer = Irp->AssociatedIrp.SystemBuffer;
if (FIELD_OFFSET(WAIT_FOR_BUFFER, Name[0]) +
WaitBuffer->NameLength > InputBufferLength) {
IoCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
return( STATUS_INVALID_PARAMETER );
}
WaitBuffer->NameLength が非常に大きい ULONG 値の場合、オフセットに追加すると整数オーバーフローが発生する可能性があります。 代わりに、ドライバーは InputBufferLength (バッファー サイズ) からオフセット (固定ヘッダー サイズ) を減算し、次の例のように WaitBuffer->NameLength (可変長データ) に十分な空き容量が残っているかどうかをテストする必要があります。
if (InputBufferLength < sizeof(WAIT_FOR_BUFFER)) {
IoCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
Return( STATUS_INVALID_PARAMETER );
}
WaitBuffer = Irp->AssociatedIrp.SystemBuffer;
if ((InputBufferLength -
FIELD_OFFSET(WAIT_FOR_BUFFER, Name[0]) <
WaitBuffer->NameLength) {
IoCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
return( STATUS_INVALID_PARAMETER );
}
つまり、バッファー サイズから固定ヘッダー サイズを引いた値が、可変長データに必要なバイト数よりも少ない場合は、エラーが返されます。
最初の if ステートメントでは InputBufferLength が WAIT_FOR_BUFFERのサイズ以上であることが保証されるため、上記の減算はアンダーフローできません。
より複雑なオーバーフローの問題を次に示します。
case IOCTL_SET_VALUE:
dwSize = sizeof(SET_VALUE);
if (inputBufferLength < dwSize) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
dwSize = FIELD_OFFSET(SET_VALUE, pInfo[0]) +
pSetValue->NumEntries * sizeof(SET_VALUE_INFO);
if (inputBufferLength < dwSize) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
この例では、乗算中に整数オーバーフローが発生する可能性があります。 SET_VALUE_INFO構造体のサイズが 2 の倍数の場合、乗算中にビットが左にシフトされると、0x80000000などの NumEntries 値がオーバーフローします。 ただし、オーバーフローによって dwSize が非常に小さく表示されるため、バッファー サイズは検証テストに合格します。 この問題を回避するには、前の例のように長さを減算し、 sizeof(SET_VALUE_INFO) で除算し、結果を NumEntries と比較します。