Share to: share facebook share twitter share wa share telegram print page

Łata (informatyka)

Łata, łatka (ang. patch) – poprawka lub uaktualnienie do programu (rzadziej do danych), przeznaczona do usunięcia pewnych problemów, błędów, rozszerzenia funkcjonalności programu albo zwiększenia wydajności 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 integrowanie z pierwotnym kodem.

Firma Microsoft używa innego nazewnictwa dla swoich poprawek. Mniejsze poprawki określane są jako software updates (aktualizacje), natomiast bardziej kompleksowe jako service packs (pakiety serwisowe).

Zadaniem łat jest zmiana kodu źródłowego albo maszynowego.

Łaty do oprogramowania dostępnego tylko w formie binarnej

Łatanie oprogramowania zamkniętego jest możliwe 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.

Mniejsze poprawki mogą być wykonywane jako modyfikacje plików binarnych, jednak ze względu na budowę plików wykonywalnych jest to trudne.

Crack jest specyficzną formą łaty, która usuwa z programu zabezpieczenia uniemożliwiające korzystanie z niego nielegalnie.

Łaty do oprogramowania z kodem źródłowym

W przypadku kodu źródłowego łaty nie muszą przechowywać całych plików, wystarczy zbiór różnic między dwiema 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%).

Przykład łaty programu diff/patch

Weźmy dla przykładu prosty program w języku C++ 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;
}

W powyższym kodzie użyto niebezpiecznego wywołania 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.

old$ ./plik Ala ma kota.
Ala ma kota. 
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().

Poniżej przedstawiono drugi program w 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:

new$ ./plik Ala ma kota.
Ala ma kota. 
new$ ./plik Ala w domu ma chomika, kota, rybki oraz psa.
Ala w domu ma chomika, kota, rybki oraz psa. 

Łatę można wygenerować poleceniem diff. Korzystając ze składni zalecanej przez podręcznik użytkownika, będzie to wyglądało tak:

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%.

Zalety łatania kodu źródłowego

Łaty 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 zastosować kilka niezależnych łat do tych samych źródeł.

Szerokie użycie łat w świecie Uniksów umożliwia istnienie wielu wersji tego samego programu, które nie muszą być szczególnie koordynowane. Zwykle jedna wersja jest wersją „główną”, a inne są wersjami pochodnymi, rozpowszechnianymi tylko jako łata do niej. 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 łat umożliwia takim wersjom pokojowe współistnienie bez konieczności dokonywania trwałych forków.

Zobacz też

Kembali kehalaman sebelumnya