2015-03-06 34 views
6

Czy nieobciążone obciążenie spowodowane odrzutem z nieokreślonego zachowania?Czy jest źle ustawione obciążenie z powodu nieokreślonego działania przesyłania?


Oto co widzę z Clang i jego odkażających:

bufhelp.h:146:29: runtime error: load of misaligned address 0x7fff04fdd0e1 for type 'const uintptr_t' (aka 'const unsigned long'), which requires 8 byte alignment 
0x7fff04fdd0e1: note: pointer points here 
00 00 00 66 66 6f 6f 62 61 72 34 32 46 4f 4f 42 41 52 31 37 66 6f 6f 62 61 72 34 33 46 4f 4f 42 
      ^

A oto gdzie obsada wchodzi w grę:

buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len) 
{ 
    ... 
    ldst = (uintptr_t *)(void *)dst; 
    lsrc1 = (const uintptr_t *)(const void *)src1; 
    lsrc2 = (const uintptr_t *)(const void *)src2; 

    for (; len >= sizeof(uintptr_t); len -= sizeof(uintptr_t)) 
    *ldst++ = *lsrc1++^*lsrc2++; 

    ... 
} 

pokrewnych, ale don” t wierzyć odpowiedzi na powyższe pytanie:

+2

Całkowicie zależy od tego, co zostanie wyświetlone w tej funkcji jako parametry. Nie widząc kodu wywołującego, nie można odpowiedzieć na to pytanie. – Lundin

+0

@Lundin - czy tak jest w przypadku? Clang już powiadomił o adresie 0x7fff04fdd0e1. Czy '0xXXXXXXX1' może być' uintptr_t * 'użytym w pętli? Czy też niepoprawnie przetwarzam dane wyjściowe Clanga? – jww

+0

Tak, ale _ dlaczego to XXX1? Musisz przekazać wskaźnik char lub coś do funkcji. W zamieszczonym kodzie nie ma nic, co powodowałoby niewspółosiowość, ponieważ wszystkie arytmetyczne wskaźniki, które tam wykonujesz, są oparte na poprawnym typie. – Lundin

Odpowiedz

6

Konwersja do błędnie dostosowała się wskaźnik jest niezdefiniowany, a nie tylko przez to wskaźnik obciążenia (C11), 6.3.2.3 (n1570 P7):

wskaźnik do typu obiekt może być przekształcany do wskaźnik do innego typu obiektu. Jeśli wynikowy wskaźnik nie jest poprawnie wyrównany [...] dla typu referencyjnego, zachowanie jest niezdefiniowane.

Kod pokazano również łamie ścisłą aliasingu, jak wskazywanego obiektu jest mało prawdopodobne, aby być zadeklarowane jako uintptr_t (adres będzie poprawnie ustawione inaczej).

Aby można było zastosować standard, można w zamian zastosować unsigned char.

Jeśli z przyczyn związanych z wydajnością skopiowano uintptr_t kawałków, można użyć unsigned char, dopóki adres nie zostanie poprawnie wyrównany, po czym nastąpi kolejne kopiowanie z pętlą uintptr_t. Należy to zrobić za pośrednictwem unii lub poprzez memcpy, aby uniknąć problemów z aliasingiem (Gcc może zoptymalizować wywołania memcpy, jeśli rozmiar jest stały).Konieczne może być ponowne skopiowanie ostatnich bajtów przez unsigned char, aby uniknąć dostępu poza granice (odczytane bajty poza tablicą nie powinny powodować problemów (Glibc robi to w kilku miejscach), ale zapis poprzez dst może zapisywać do innego obiekt). Może pomóc restrict - zakwalifikować używane wskaźniki.

+1

Edytowano część dostępu poza obszarem. Nie powinienem dawać rady, aby zignorować UB przed moją pierwszą kawą ... – mafso

1

Myślę, że odpowiedź na Twoje pytanie brzmi „tak” - choć nie jestem pewien, że to specyficzne dla samej obsadzie, ale aligné wskaźników w generał. Kod wewnętrzny buf_xor() wygląda dla mnie w zasadzie dobrze, więc sprawdziłbym, jakie adresy są przekazywane.

Wygląda na to, że nie chcesz wywoływać buf_xor() z niepodpisanymi adresami. Jeśli to nie jest to (jeśli wywołujesz but_xor() wszędzie z wyrównanymi adresami), wtedy upewnię się, że uintptr_t jest zdefiniowane jako to samo (a dokładnie 64 bity na podstawie twojego wyjścia) gdzie buf_xor() jest skompilowany, a także, gdzie się go nazywa.

Jedna ostateczna opinia osobista jest taka, że ​​ponieważ implementacja buf_xor() wymaga wyrównanych wskaźników jako parametrów w niektórych implementacjach procesorów/kompilatorów, prawdopodobnie można zapisać pewne kłopoty w przyszłości, zmieniając podpis, aby to odzwierciedlić (zmień void * na uintptr_t *)) - lub zmienić samą implementację, aby radzić sobie z gracją, "ręcznie", z niepodpisanymi adresami na wszystkich architekturach.

+0

To jest faktycznie kod GnuPG, który analizuję i testuję akceptację. Chciałem rozwiązać problem ze związkami zawodowymi lub dostosować wskaźniki do rozmówców. Ale w wielu miejscach stało się łatwiejsze naprawienie funkcji za pomocą 'memcpy' w tymczasowy. Złożę raport o błędzie, aby ostrzec ich o problemie (zobacz [Problem 1881: Niezdefiniowane zachowanie podczas uruchamiania 'make check' pod działem odkażania Clang] (https://bugs.g10code.com/gnupg/issue1881)). – jww