2012-03-25 4 views
10

Hace algunos años, mi servidor web cambió de 32 bits a 64 bits, y un script PHP crítico dejó de funcionar. Fue debido a que las operaciones < < y >> (cambio de bit) han cambiado. Yo era capaz de solucionar mi problema mediante la sustitución de las rutinas rotateleft y rotateright con rotateleft32 y rotateright32 así:Conversión de funciones complejas de Giro PHP para trabajar en 64-bit

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); 
} 

Ahora he encontrado con un nuevo conjunto de código que parece ser exactamente el mismo problema, pero es más complicado:

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; 
} 

tengo tres problemas al tratar de solucionar este problema a mí mismo:

  1. no es mi código, así que no estoy familiarizado con lo que está tratando de hacer.
  2. Ya no tengo un servidor de 32 bits para probarlo contra
  3. Soy adecuado, pero no un experto en PHP.

Me gustaría saber si alguien ve una solución simple para permitir que este código funcione en un servidor de 64 bits y brinde el mismo resultado que en un servidor de 32 bits.

Si no es así, ¿cómo recomendaría que depure esto dado que no tengo un resultado de 32 bits para comparar?


Aquí es un poco de discusión con respecto a este problema, y ​​un intento de conseguir el desarrollador para solucionarlo: How to get the outdated 32bit keymaker.php Script Working on 64 bit

+3

Es necesario configurar una versión de 32 bits de PHP, tal vez mediante la ejecución de una primera máquina virtual de 32 bits. –

+0

Además, si no puede hacer una comparación cara a cara, ¿cómo sabe que el problema es el código anterior? –

+0

@OliCharlesworth: Es una conjetura, basada en la solución que necesitaba originalmente y sobre la cuestión relacionada Stackoverflow entonces me había pedido: http://stackoverflow.com/questions/397738/32-to-64-bit-gotchas-in -php – lkessler

Respuesta

26

responder a todas cuatro de sus preguntas:

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

Si bien podría entrar en los procedimientos de búsqueda y depuración en detalle, en su lugar, recomendaré los clásicos. I highly recomienda picking this up si este es su trabajo diario o si tiene más que un interés pasajero en refactorizar el código en el futuro.

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

Según lo mencionado por Oli en la fe de erratas, tendrá que configurar una 32-bit VM o chroot, depende del sistema operativo del servidor está en ejecución.

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

Como el anterior, si esto es más que un problema de punto, recomiendo theclassics.

  4. (Fijación del código real)

En primer lugar, eww. Sin documentación, comentario cruzado, lógica duplicada y nombres de variables inexpresivos que no encapsulan su lógica de manera efectiva. No es el peor código que he visto, pero siento empatía contigo aquí.

Aún así, el resultado no es necesariamente incorrecto. Si no tiene una serie de pruebas unitarias en su base de código, I recommend adding them.

Si desea comparar la eficiencia de esta función, le recomiendo que la compare con los resultados de the algorithms defined in the notes here. Idealmente, querrá una de las implementaciones closest to this reference implementation.

Stealing uno de la parte superior de ese hilo y reutilizarlo a su 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; 
} 

(. No es de extrañar que esta tiene una apariencia similar a la aplicación que ya ha proporcionado inicialmente)

¿Por qué estoy incluyendo $amount como parte de la especificación? Simple: no infringe encapsulation como el código que está refactorizando. Parece que se puede establecer en ($copya->e[0] & ECC_UPRBIT) ? 1 : 0 según sea necesario.

En resumen: la forma más fácil de refactorizar código no es necesariamente mirar su lógica contenida. Algunas veces, solo es necesario determinar la intención y encontrar una buena implementación de referencia.

+0

+1 Respuesta genial y educativa, ¿eres profesor por casualidad? –

+8

@andreas Alas, solo el engendro de dos de ellos. Solo soy un humilde investigador de cáncer en el momento de escribir este artículo. :) – MrGomez