Jedno rzutowanie może zmienić pozornie zwyczajny pomocnik ustawień proxy w awarię zależną od architektury:

current = (IntPtr)((int)current + optionSize);

Ten kod zawęża adres natywny do 32-bitowej liczby całkowitej, zanim doda rozmiar następnej struktury. Proces 64-bitowy może przechowywać adresy, które się nie mieszczą. W zależności od konwersji i wartości wynikiem może być wyjątek przepełnienia lub nieprawidłowy adres. Powrót kompilacji do x86 może ukryć błąd, ale pozostawia implementację interopu zależną od tego obejścia.

Przechowuj adresy w formie rozmiaru wskaźnika. Na przykład do przechodzenia po już przydzielonej tablicy można użyć:

IntPtr item = IntPtr.Add(buffer, checked(index * optionSize));

Przesunięcie pozostaje liczbą całkowitą; sam adres nie jest przez nią przepychany. Rozmiar przydziału i indeks nadal muszą być prawidłowe.

Następnie przejrzyj otaczające deklaracje

Opcje WinINet dla każdego połączenia zawierają unię, której składowe obejmują DWORD, wskaźnik do ciągu i FILETIME. Pola wskaźników wymagają IntPtr; pola DWORD pozostają 32-bitowe. Wyrównanie natywne ma znaczenie, więc zastępowanie każdej liczby całkowitej 64-bitową liczbą całkowitą lub wymuszanie upakowanego układu nie jest solidną naprawą.

Używaj rozmiaru struktury po marshalingu podczas przechodzenia po tablicy, konsekwentnie dopasowuj deklarację ANSI lub Unicode i śledź każdy przydział osobno. Zwolnienie bloku struktur opcji nie zwalnia automatycznie ciągów przydzielonych gdzie indziej i wskazywanych przez te struktury.

Na koniec oddziel kwestię zakresu ustawień od poprawności pamięci. Naprawa rzutowania nie dowodzi, że wybrana opcja WinINet wpływa tylko na jedną kontrolkę, jeden proces lub ustawienia bieżącego użytkownika. Sprawdź to zachowanie API, zanim przyjmiesz resztę starego przykładu. Jeśli wysyła również powiadomienia o odświeżeniu, wybierz je dla zamierzonego zakresu.

Powiązane artykuły