Łata (informatyka)
Z Wikipedii
Łata, Łatka (ang. patch) – jest to poprawka lub uaktualnienie do programu bądź gry (rzadziej danych), przeznaczona do usunięcia pewnych problemów, błędów, rozszerzenia funkcjonalności programu albo zwiększenia wydajności (ang. performance) wcześniejszej wersji programu.
Termin ten powstał prawdopodobnie jako komenda systemu Unix (patch) wprowadzona przez Larry'ego Walla, aby ułatwić wymienianie się poprawkami kodu źródłowego i umożliwić ich szybkie, zautomatyzowane aplikowanie do oryginalnego kodu.
Firma Microsoft używa innej terminologii dla swoich poprawek. Mniejsze poprawki nazywane są software updates (aktualizacje), natomiast te bardziej kompleksowe określane są jako service packs (pakiety serwisowe).
Łaty bazują na różnicach pomiędzy stanem poprawionym a poprawianym. Ich zadaniem jest zmiana zastanego stanu kodu (czy to źródłowego, czy binarnego).
Spis treści |
[edytuj] Łaty do oprogramowania dostępnego tylko w formie binarnej
Łatanie oprogramowania zamkniętego jest możliwe tylko i wyłącznie poprzez łaty zmieniające pliki binarne, z uwagi na brak dostępności źródeł. Najprostsze łaty po prostu nadpisują pliki wymagające poprawienia ich poprawionymi wersjami. Wiąże się to z koniecznością umieszczenia w programie dokonującym aktualizacji całych plików (najczęściej poddanych uprzednio kompresji). Łaty takie mogą mieć rozmiar dochodzący do kilkuset MB.
Oczywiście mniejsze poprawki mogą być wykonywane jako modyfikacje plików binarnych, jednak ze względu na budowę plików wykonywalnych jest to bardzo trudne. Crack jest specyficzną formą łaty, która usuwa z programu zabezpieczenia uniemożliwiające korzystanie z niego nielegalnie.
[edytuj] Łaty do oprogramowania z kodem źródłowym
W przypadku kodu źródłowego laty nie muszą przechowywać całych plików, wystarczy zbiór różnic między dwoma wersjami pliku. Plik z łatą generowany jest najczęściej programem diff, a nakładany poleceniem patch. Łata taka może mieć rozmiar kilkudziesięciu MB, jednak z uwagi na zapisanie w niej informacji w postaci tekstowej łaty te doskonale się kompresują (często kompresja redukuje rozmiar łaty nawet o 75%).
[edytuj] Przykład łaty programu diff/patch
Weźmy dla przykładu prosty program zawierający błąd:
#include <iostream> int main ( int argc, char **argv) { char text[20] = {0}; for ( int i = 1; i < argc; ++i ) { strcat (text, argv[i]); strcat (text, " "); } std::cout << text << std::endl; return 0; }
Zwróć uwagę na niebezpieczne wywołanie strcat() bez kontroli długości łańcucha argv[i], który może nie zmieścić się w pamięci przeznaczonej dla zmiennej text.
kb@techie:~/ala/old$ ./plik Ala ma kota. Ala ma kota. kb@techie:~/ala/old$ ./plik Ala w domu ma chomika, kota, rybki oraz psa. Ala w domu ma chomika, kota, rybki oraz psa. Naruszenie ochrony pamięci
Zgodnie z przewidywaniami, dane, które nie mieszczą się w pamięci dla nich przeznaczonej nadpisują adres powrotu funkcji main().
Przyjrzyjmy się drugiemu programowi (poprawionej wersji):
#include <iostream> #include <string> using namespace std; int main ( int argc, char **argv) { string text; for ( int i = 1; i < argc; ++i ) { text += string(argv[i]) + " "; } cout << text << endl; return 0; }
Ta wersja nie korzysta z niebezpiecznego wywołania strcat() i używa typu string, który automatycznie zarządza swoją pamięcią.
Testowanie programu potwierdza, że błąd w nim nie występuje:
kb@techie:~/ala/new$ ./plik Ala ma kota. Ala ma kota. kb@techie:~/ala/new$ ./plik Ala w domu ma chomika, kota, rybki oraz psa. Ala w domu ma chomika, kota, rybki oraz psa.
Patch możemy wygenerować poleceniem diff. Skorzystamy ze składni zalecanej przez manual.
kb@techie:~/ala/old$ LC_ALL=C TZ=UTC0 diff -Naur old new > plik.patch
Po wykonaniu tej komendy plik.patch będzie miał 543 bajty i następującą zawartość:
diff -Naur old/plik.C new/plik.C --- old/plik.C 2004-08-11 11:44:16.000000000 +0000 +++ new/plik.C 2004-08-11 11:48:15.000000000 +0000 @@ -1,19 +1,21 @@ #include <iostream> +#include <string> + +using namespace std; int main ( int argc, char **argv) { - char text[20] = {0}; + string text; for ( int i = 1; i < argc; ++i ) { - strcat (text, argv[i]); - strcat (text, " "); + text += string(argv[i]) + " "; } - std::cout << text << std::endl; + cout << text << endl; return 0; }
Program gzip skompresował ten plik do 322 bajtów, czyli o 46%.
[edytuj] Zalety łatania kodu źródłowego
Patche mają dwie ważne przewagi nad rozpowszechnianiem nowych wersji programu. Po pierwsze są mniejsze. Po drugie, o ile zmiany nie kolidują ze sobą można zaaplikować kilka niezależnych patchy do tych samych źródeł.
Szerokie użycie patchy w świecie Uniksów umożliwia istnienie wielu wersji tego samego programu które nie muszą być szczególnie koordynowane - zwykle jedna z nich jest wersją "główną", a inne są wersjami pochodnymi, rozpowszechnianymi tylko jako patch do odpowiedniej wersji głównej. W ten sposób działają prawie wszystkie dystrybucje mając własne wersje rozwijanych zewnętrznie programów zintegrowane z resztą dystrybucji. Tak działa też rozwój Linuksa, gdzie poza główną wersją istnieje mnóstwo odgałęzień, dystrybucyjnych, lub modyfikujących jądro w pewnym kierunku (np. dodając eksperymentalny kod, poprawiając bezpieczeństwo, dostosowując do szczególnych warunków itd.). System patchy umożliwia takim wersjom pokojowe współistnienie bez konieczności dokonywania trwałych forków.
Zobacz też: service pack