zlib to jeden z niewielu fragmentów kodu w języku C pochodzących od zewnętrznych dostawców, które znajdują się wewnątrz sgcWebSockets. Odpowiada za rozszerzenie WebSocket permessage-deflate, więc każda skompresowana ramka wysyłana lub odbierana przez Twój serwer przez niego przechodzi, a także obsługuje kodowanie treści HTTP. sgcOpenAPI korzysta z tego samego źródła, więc używa tej samej kopii. Od wersji 2026.8.0 ta kopia przechodzi z zlib 1.2.12 na zlib 1.3.1.
Zmiana jest niewidoczna w API. Nic w Twoim kodzie nie wymaga modyfikacji, a zachowanie kompresji pozostaje bez zmian. Warto natomiast wyjaśnić, dlaczego podniesienie wersji niewielkiej biblioteki w języku C to coś więcej niż podmiana pliku, oraz co zrobiliśmy, aby mieć pewność, że jest to bezpieczne na każdym obsługiwanym przez nas kompilatorze.
Co naprawia 1.3.1 i dlaczego nie byłeś narażony
Najważniejszą poprawką pomiędzy 1.2.12 a 1.3.1 jest CVE-2022-37434, odczyt poza zakresem sterty w funkcji inflate(). Jest ona osiągalna tylko wtedy, gdy aplikacja wywołująca przekaże do zlib strukturę gz_header, której pole extra wskazuje na bufor. zlib kopiuje wtedy do niego dodatkowe pole gzip, a w wersji 1.2.12 w tym kopiowaniu brakowało sprawdzenia granic.
sgcWebSockets nigdy nie spełniał tego warunku. Wywołuje inflateGetHeader wyłącznie z wyzerowaną strukturą gz_header i nigdy nie przypisuje head.extra, więc wejście do tej gałęzi kodu nie było możliwe. Sprawdziliśmy to w kodzie źródłowym, zanim zdecydowaliśmy, co zrobić, i mówimy to wprost: aplikacje zbudowane z wcześniejszymi wersjami nie były podatne tą drogą.
Mimo to wykonaliśmy aktualizację. To ciągi znaków z wersją, a nie grafy wywołań, są tym, co odczytują automatyczne skanery i kwestionariusze dostawców, a klient uruchamiający skanowanie zależności nie powinien musieć odtwarzać naszego toku rozumowania, żeby zamknąć zgłoszenie. Aktualizacja kończy tę dyskusję, zamiast wymuszać jej wielokrotne powtarzanie.
Dlaczego aktualizacja zlib to nie podmiana pliku
zlib jest kompilowany do Twojego pliku wykonywalnego, a nie dostarczany jako DLL, dlatego aplikacja sgcWebSockets nie ma obok siebie pliku zlib1.dll. To linkowanie odbywa się przy użyciu wstępnie skompilowanych plików obiektowych, a Delphi jest wymagające co do ich formatu. Aktualizacja zlib oznacza więc przebudowanie tych plików obiektowych, a nie ma jednego zestawu, lecz trzy.
| Używane przez | Format | Zbudowane przy użyciu |
|---|---|---|
| Delphi 7 do XE | OMF | bcc32, ZEXPORT=__fastcall |
| XE2 i nowsze, Win32 | OMF | bcc32, ZEXPORT=__cdecl |
| XE2 i nowsze, Win64 | COFF | MSVC cl |
Oba zestawy 32-bitowe różnią się konwencją wywołań, ponieważ starsze kompilatory linkują zlib z konwencją rejestrową Delphi, natomiast XE2 i nowsze używają cdecl. Zestaw 64-bitowy to z kolei inny format plików obiektowych. Warto zauważyć, że bcc64 nie potrafi go wygenerować, ponieważ tworzy pliki obiektowe ELF, a linker Delphi dla Win64 oczekuje formatu COFF, dlatego ten zestaw budowany jest kompilatorem Microsoftu.
Nic z tego nie jest dla Ciebie widoczne. To po prostu powód, dla którego podniesienie wersji zlib jest zadaniem kompilacyjnym, a nie pobraniem pliku.
Zweryfikowane na każdym kompilatorze, nie tylko na najnowszym
Przebudowane pliki obiektowe mogą się poprawnie kompilować, a mimo to być błędne, więc sam test linkowania nie wystarczy. Każdy obsługiwany kompilator posłużył do zbudowania, a następnie uruchomienia programu, który kompresuje bufor, dekompresuje go, porównuje bajt po bajcie i sprawdza, czy zlinkowane pliki obiektowe zgłaszają oczekiwaną wersję.
uses
sgcIdCTypes, sgcIdGlobal, sgcIdZLibHeaders;
var
vPackedLen: TIdC_ULONG;
begin
vPackedLen := SizeOf(vPacked);
if compress(PIdAnsiChar(@vPacked[0]), vPackedLen,
PIdAnsiChar(@vSrc[0]), SizeOf(vSrc)) <> 0 then
raise Exception.Create('compress failed');
WriteLn('zlib ', String(AnsiString(zlibVersion))); // zlib 1.3.1
end;
Program ten działał na Delphi 7, Delphi 2007, Delphi 2009 oraz RAD Studio od XE6 do 13, na Win32 i na Win64 tam, gdzie ta platforma istnieje. Wszystkie 25 kombinacji przechodzi test i zgłasza wersję 1.3.1.
Ukryty błąd 64-bitowy naprawiony przy okazji
Macierz testów wychwyciła coś, co nie miało nic wspólnego z nową wersją. W Delphi 10 Seattle kompilacje 64-bitowe wybierały pliki obiektowe 32-bitowe, których nie da się zlinkować do 64-bitowego pliku wykonywalnego, co powodowało błąd Bad object file format. Przyczyną była stara dyrektywa warunkowa, mająca obejść problem charakterystyczny dla Seattle, która kierowała tę jedną kombinację do niewłaściwego zestawu plików obiektowych. Seattle w wersji 64-bitowej używa teraz tych samych plików obiektowych co każda inna platforma 64-bitowa i kompiluje się poprawnie.
sgcOpenAPI otrzymuje tę samą aktualizację
sgcOpenAPI współdzieli kod źródłowy z sgcWebSockets, w tym zlib, więc przechodzi na 1.3.1 w tym samym wydaniu, bez żadnych dodatkowych działań z Twojej strony.
Co musisz zrobić
Zainstaluj wersję 2026.8.0 i przebuduj swoje projekty. Nie ma żadnej właściwości do ustawienia, żadnego modułu do dodania ani usunięcia i żadnej zmiany we wdrożeniu, ponieważ zlib był już wewnątrz Twojego pliku wykonywalnego i nadal tam jest. Jeśli prowadzisz zestawienie komponentów oprogramowania dla własnego produktu, zaktualizuj wpis zlib do wersji 1.3.1 i możesz usunąć wszelkie notatki dotyczące CVE-2022-37434, które do tej pory utrzymywałeś.
