Historia problemu
Bezpieczne kopiowanie pamięci to jedno z najczęstszych i najbardziej krytycznych zadań w C. Początkowo programy używały pętli do kopiowania bajtów. Później dodano standardowe funkcje: memcpy, memmove, a także bardziej zabezpieczone alternatywy, takie jak strncpy dla łańcuchów. Niewłaściwe kopiowanie prowadzi do przepełnień buforów i luk w bezpieczeństwie.
Problem
Użycie niewłaściwej funkcji lub błędnego rozmiaru podczas kopiowania może zniszczyć dane lub nawet otworzyć drogę do ataków osobom trzecim. Rozróżnienie przypadków, w których używa się memmove, a kiedy memcpy, jest kluczowe dla uniknięcia błędów związanych z nakładającymi się obszarami pamięci.
Rozwiązanie
Do bezpiecznego kopiowania pamięci niena stronie tekstowej użyj:
memcpy(dest, src, n);
memcpy szybko kopiuje n bajtów z src do dest, jeśli ich obszary pamięci się nie nakładają.memmove:memmove(dest, src, n);
Do kopiowania łańcuchów użyj albo strncpy, albo lepiej nowoczesnych i zabezpieczonych alternatyw, jeśli są dostępne (strlcpy).
Kluczowe cechy:
memcpy jest bezpieczny tylko przy braku nakładania src i dest.memmove poprawnie działa nawet z nakładającymi się obszarami pamięci.1. Czym różni się memcpy od memmove i kiedy która funkcja jest potrzebna?
memcpy działa bardzo szybko, ale nie jest przeznaczony do nakładających się obszarów pamięci - wynik będzie nieprzewidywalny. memmove gwarantuje poprawne kopiowanie niezależnie od nakładania:
int arr[] = {1,2,3,4,5}; // memmove: bezpiecznie kopiujemy z nakładaniem memmove(arr+1, arr, 4 * sizeof(int));
2. Czy bezpiecznie jest używać strcpy do kopiowania łańcucha do mniejszego bufora?
Nie, funkcja strcpy nie sprawdza rozmiaru bufora docelowego. Często prowadzi to do przepełnienia bufora. Lepiej użyć strncpy, lub strlcpy (jeśli dostępne), albo jawnie kontrolować rozmiar:
char dest[5]; strncpy(dest, src, sizeof(dest)-1); // src musi być krótszy niż 5 znaków
3. Czy można używać memcpy do kopiowania struktur z wskaźnikami?
Tak, ale to kopiuje tylko same wskaźniki, a nie dane pod tymi adresami. Może to prowadzić do błędów podczas pracy z pamięcią i podwójnego zwalniania.
Kopiowana jest długa linia do małego bufora za pomocą strcpy bez sprawdzania długości źródła. Dochodzi do przepełnienia bufora, co prowadzi do luki w zabezpieczeniach.
Zalety:
Wady:
Używa się strncpy lub memmove z dokładną kontrolą rozmiaru, ręcznie zapewniając końcowy zerowy znak łańcucha.
Zalety:
Wady: