2012-03-25 10 views
10

Kilka lat temu mój webhost zmienił się z 32-bitowego na 64-bitowy, a krytyczny skrypt PHP przestał działać. Było to spowodowane zmianą operacji < < i >> (przesunięcie bitowe). Udało mi się rozwiązać mój problem, zastępując rotateleft i rotateright rutyny z rotateleft32 i rotateright32 tak:Konwersja złożonych funkcji PHP do pracy z 64-bitowymi kodami

function rotateleft($value, $numleft) { 
    return (($value << $numleft) | ($value >> (32-$numleft))); 
} 
function rotateleft32($value, $numleft) { 
    return ((($value << $numleft) | ($value >> (32-$numleft))) & 0xFFFFFFFF); 
} 

function rotateright($value, $numright) { 
    return (($value >> $numright) | ($value << (32-$numright))); 
} 
function rotateright32($value, $numright) { 
    return ((($value >> $numright) | ($value << (32-$numright))) & 0xFFFFFFFF); 
} 

Mam teraz natknąć nowego zestawu kodu, który wydaje się być dokładnie taki sam problem, ale jest bardziej skomplikowane:

function ECC_RotateLeft($a) 
{ 
    $copya = makecopy($a); 
    $bit = ($copya->e[0] & ECC_UPRBIT) ? 1 : 0; 

    /* looped 
    for ($i = 0; $i < ECC_MAXLONG - 1; $i++) 
    $copya->e[$i] = ($copya->e[$i] << 1) | (($copya->e[$i + 1] & ECC_MSB) ? 1 : 0); 
    $copya->e[0] &= ECC_UPRMASK; 
    looped */ 

    /* unlooped */ 
    // These lines are optimized for ECC_MAXLONG==4 only! 
    $bit = ($copya->e[0] & ECC_UPRBIT) ? 1 : 0; 
    $copya->e[0] = (($copya->e[0] << 1) & ECC_UPRMASK) | (($copya->e[1] & ECC_MSB) ? 1 : 0); 
    $copya->e[1] = ($copya->e[1] << 1) | (($copya->e[2] & ECC_MSB) ? 1 : 0); 
    $copya->e[2] = ($copya->e[2] << 1) | (($copya->e[3] & ECC_MSB) ? 1 : 0); 
    /* unlooped */ 

    $copya->e[3] = ($copya->e[3] << 1) | $bit; 
    return $copya; 
} 

function ECC_RotateRight($a) 
{ 
    $copya = makecopy($a); 
    $bit = ($copya->e[ECC_NUMWORD] & 1) ? ECC_UPRBIT : 0; 

    /* looped 
    for ($i = ECC_MAXLONG - 1; $i > 0; $i--) 
    $copya->e[$i] = (($copya->e[$i] >> 1) & 0x7FFFFFFF) | (($copya->e[$i - 1] & 1) ? ECC_MSB : 0); 
    looped */ 

    /* unlooped */ 
    // Thes lines are optimized for ECC_MAXLONG==4 only! 
    $copya->e[3] = (($copya->e[3] >> 1) & 0x7FFFFFFF) | (($copya->e[2] & 1) ? ECC_MSB : 0); 
    $copya->e[2] = (($copya->e[2] >> 1) & 0x7FFFFFFF) | (($copya->e[1] & 1) ? ECC_MSB : 0); 
    $copya->e[1] = (($copya->e[1] >> 1) & 0x7FFFFFFF) | (($copya->e[0] & 1) ? ECC_MSB : 0); 
    /* unlooped */ 

    $copya->e[0] = (($copya->e[0] >> 1) & 0x7FFFFFFF) | $bit; 
    return $copya; 
} 

mam trzy problemy, próbując naprawić sobie:

  1. to nie jest mój kod, więc nie jestem obeznany z tym, co próbuje zrobić.
  2. Nie mam już 32-bitowego serwera do przetestowania go przed
  3. Jestem odpowiedni, ale nie jestem ekspertem od PHP.

Chciałbym wiedzieć, czy ktoś widzi prostą poprawkę, aby ten kod działał na 64-bitowym serwerze i daje taki sam wynik, jaki miałby na serwerze 32-bitowym.

Jeśli nie, jak poleciłbym debugowanie, biorąc pod uwagę, że nie mam 32-bitowego wyniku do porównania?


Oto dyskusja dotycząca tego problemu i próba uzyskania dewelopera to naprawić: How to get the outdated 32bit keymaker.php Script Working on 64 bit

+3

Powinieneś skonfigurować 32-bitową wersję PHP, prawdopodobnie przez uruchomienie 32-bitowej maszyny wirtualnej. –

+0

Ponadto, jeśli nie jesteś w stanie wykonać porównania bezpośredniego, skąd wiesz, że to powyższy kod jest problemem? –

+0

@OliCharlesworth: To wyedukowane przypuszczenie, oparte na poprawce, której potrzebowałem pierwotnie i na pokrewnym pytaniu Stackoverflow, które wtedy zadałem: http://stackoverflow.com/questions/397738/32-to-64-bit-gotchas-in -php – lkessler

Odpowiedz

26

Odbieranie wszystkich cztery od pytania:

  1. It is not my code, so I am not familiar with what it is trying to do.

Chociaż mogłem szczegółowo zapoznać się z procedurami śledzenia i debugowania, zamiast tego zalecę klasykę. I wysoce polecam picking this up jeśli jest to Twoja codzienna praca lub masz więcej niż przelotne zainteresowanie refaktoryzacją kodu w przyszłości.

  2. I no longer have a 32-bit server to test it against

Jak wspomniano przez Oli w errata, będziemy chcieli, aby uruchamiamy 32-bit VM lub chroot, w zależności od systemu operacyjnego serwer jest uruchomiony.

  3. I am adequate, but not an expert in PHP.

Jak wyżej, jeśli jest to więcej niż tylko kwestia miejscu, polecam theclassics.

  4. (Ustalenie właściwego kodu)

pierwsze, eww. Brak dokumentacji, komentarz cruftu, powielonej logiki i nieoczekiwanych nazw zmiennych, które nie potrafią efektywnie hermetyzować swojej logiki. To nie jest najgorszy kod jaki widziałem, ale wczuwam się w ciebie tutaj.

Mimo to wynik niekoniecznie musi być błędny. Jeśli nie masz serii testów jednostkowych dla niego w bazie kodu, I recommend adding them.

Jeśli chcesz porównać wydajność tej funkcji, zdecydowanie zalecamy porównanie jej z wynikami the algorithms defined in the notes here. Najlepiej, jeśli chcesz jedną z implementacji closest to this reference implementation.

Kradzież jeden w górnej części tego wątku i przełożenie go do API:

function ECC_RotateLeft($value,$amount) { 
    if ($amount>0) { 
     $amount %= 32; 
     $value = ($value<<$amount) | ($value>>(32-$amount)); 
    } 
    return $value; 
} 

function ECC_RotateRight($value,$amount) { 
    if ($amount>0) { 
     $amount %= 32; 
     $value = ($value>>$amount) | ($value<<(32-$amount)); 
    } 
    return $value; 
} 

(. Nic dziwnego, że ten wygląda podobnie do realizacji początkowo przewidzianego)

Dlaczego tym $amount w ramach specyfikacji? Proste: nie narusza ona kodu encapsulation, podobnie jak kod, który refaktoryzujesz. Wygląda na to, że w razie potrzeby można ustawić na ($copya->e[0] & ECC_UPRBIT) ? 1 : 0.

W skrócie: najprostszym sposobem na kod refaktoryzacji niekoniecznie jest analiza zawartej w nim logiki. Czasami, określenie celu i znalezienie dobrej implementacji referencyjnej jest wszystkim, co jest potrzebne.

+0

+1 Wielka i pouczająca odpowiedź, czy jesteś nauczycielem przez przypadek? –

+8

@andreas Niestety, tylko odrodzenie dwóch z nich. Jestem tylko skromnym badaczem raka w momencie pisania tego tekstu. :) – MrGomez

Powiązane problemy