Przekroczenie zakresu liczb całkowitych

Przekroczenie zakresu liczb całkowitych (ang. integer overflow) – błąd programistyczny spowodowany nieprawidłowym oszacowaniem zakresu wartości, które może przyjąć zmienna w trakcie pracy programu. Możliwą konsekwencją błędu tego typu jest nadpisanie pamięci poprzedzającej bufor lub przepełnienie bufora, co w konsekwencji może prowadzić do przejęcia kontroli nad podatną aplikacją przez osobę trzecią.

Szczegóły techniczne

Użyta architektura sprzętowa-programowa determinuje rozmiar danych typu całkowitego. Najczęściej mają one pojemność 8, 16, 32, 64 lub 128 bitów; parametr ten wynika z charakterystyki rejestrów procesora oraz konwencji obowiązujących w danym języku programowania. Dodatkowo, ustalony jest sposób reprezentacji liczb dodatnich i ujemnych, najczęściej z wykorzystaniem kodu uzupełnień do dwóch.

Rezultat operacji arytmetycznej może wykroczyć poza dostępny zakres użytego w obliczeniach typu danych. W takiej sytuacji, zwykle dochodzi do utraty najstarszych bitów wyniku (efekt slangowo określany jako przekręcenie się licznika) i ustawienia flagi przeniesienia (carry flag) w rejestrze stanu, która informuje programistę o nieprawidłowości wyniku.

Niektóre języki nie przewidują automatycznego sprawdzania wspomnianej flagi: w standardzie ISO C99 wynik operacji, dla której zachodzi błąd przekroczenia zakresu liczb całkowitych, jest po prostu niezdefiniowany. W takiej sytuacji może dojść do kilku nieprzewidzianych przez programistę sytuacji:

  • jeśli zmienna używana jest jako licznik, program może w efekcie nie doszacować rozmiar danych, które pobrano do pamięci od użytkownika (na przykład: pobrano 257 bajtów, ale licznik jest 8-bitowy i przyjmuje wartość 1) – co może doprowadzić do nadpisania bufora przy kopiowaniu danych;
  • jeśli zmienna ze znakiem używana jest jako indeks tablicy, może dojść do zmiany znaku zmiennej i odwołania się do pamięci znajdującej się przed tablicą (ujemny indeks) – co zwykle spowoduje nadpisanie struktur kontrolnych programu.

Nawet jeśli sama zmienna licznikowa jest należycie chroniona przed przekroczeniem dopuszczalnego zakresu wartości, w pewnych sytuacjach – między innymi w funkcji calloc() – dochodzi do ukrytego mnożenia parametru przez rozmiar pojedynczego elementu, aby otrzymać wielkość obszaru, który powinien zostać zaalokowany. Na przykład, gdy programista chce zaalokować pamięć na 1000 elementów o rozmiarze 16 bajtów, funkcja przydzieli obszar wielkości 1000 * 16, czyli 16000 bajtów. Przeoczenie takiej sytuacji może prowadzić do subtelnych i trudnych do wykrycia błędów programu.

Implikacje dla bezpieczeństwa aplikacji

Błędy przekroczenia zakresu liczb całkowitych prowadzą często do zagrożenia bezpieczeństwa aplikacji. Dzieje się tak w środowisku, w którym kontrolowany przez osobę trzecią błąd przekroczenia zakresu liczb całkowitych nie powoduje sytuacji wyjątkowej, lub w którym ta sytuacja nie jest obsłużona prawidłowo.