Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Ovladače často přijímají vstupní vyrovnávací paměti s pevnými záhlavími a koncovými daty proměnlivé délky, jako v následujícím příkladu:
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 );
}
Pokud je WaitBuffer-NameLength> velmi velká hodnota typu ulong, přičtení k posunu může způsobit přetečení celého čísla. Místo toho by ovladač měl odečíst posun (pevná velikost záhlaví) od inputBufferLength (velikost vyrovnávací paměti) a otestovat, jestli výsledek ponechá dostatek místa pro WaitBuffer-NameLength> (data o délce proměnné), jak je znázorněno v následujícím příkladu:
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 );
}
Jinými slovy, pokud velikost vyrovnávací paměti minus pevná velikost záhlaví ponechá méně než počet bajtů požadovaných pro data s proměnnou délkou, signalizujeme chybu.
Výše uvedené odčítání nemůže přetéct, protože první příkaz if zajišťuje, že InputBufferLength je větší nebo roven velikosti WAIT_FOR_BUFFER.
Následující příklad ukazuje složitější problém s přetečením:
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;
}
V tomto příkladu může během násobení dojít k přetečení celého čísla. Pokud je velikost struktury SET_VALUE_INFO násobkem 2, hodnota, jako je NumEntries 0x80000000, způsobí přetečení, když se bity během násobení posunou doleva. Velikost vyrovnávací paměti však projde ověřovacím testem, protože přetečení způsobí, že dwSize bude vypadat poměrně malá. Chcete-li se tomuto problému vyhnout, odečtěte délky jako v předchozím příkladu, vydělte je velikostí(SET_VALUE_INFO) a porovnejte výsledek s NumEntries.