2012-03-25 3 views
10

몇 년 전 웹 호스트가 32 비트에서 64 비트로 변경되었으며 중요한 PHP 스크립트가 작동을 멈췄습니다. < < 및 >> (비트 시프트) 연산이 변경 되었기 때문입니다. 나는이 같은 rotateleft32 및 rotateright32으로 rotateleft 및 rotateright 루틴을 대체하여 내 문제를 해결할 수 있었다 : 지금 정확히 같은 문제가 될 것으로 보인다 코드의 새로운 세트를 가로 질러 온64 비트에서 작동하도록 복잡한 PHP 회전 함수

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

, 그러나 그것은이다 나는이에게 자신을 해결하기 위해 노력 세 가지 문제가

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

: 더 복잡 그것은 내 코드가 아닙니다

  1. , 그래서 나는 일을하려고 무슨에 익숙하지 않다.
  2. 더 이상 테스트 할 32 비트 서버가 없습니다.
  3. 나는 적당하지만 PHP 전문가는 아닙니다.

누구나이 코드가 64 비트 서버에서 작동하고 32 비트 서버에서와 동일한 결과를 제공하는 간단한 수정 방법을 알고 싶습니다.

그렇지 않은 경우 비교할 32 비트 결과가 없으므로이 디버깅을 어떻게 권장합니까? 응답 How to get the outdated 32bit keymaker.php Script Working on 64 bit

+3

아마도 처음에는 32 비트 VM을 실행하여 32 비트 버전의 PHP를 설치해야합니다. –

+0

또한 일대일 비교를 수행 할 수 없다면 위의 코드가 문제인지 어떻게 알 수 있습니까? –

+0

@OliCharlesworth : 원래 필자가 필요로했던 수정본과 관련된 Stackoverflow 질문에 기반한 교양있는 추측입니다. http://stackoverflow.com/questions/397738/32-to-64-bit-gotchas-in -php – lkessler

답변

26

당신의 모든 질문에 :

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

다음

이 문제에 대한 논의, 그리고 그것을 해결하기 위해 개발자를 얻기 위해 시도이다

추적 및 디버깅 절차를 자세히 설명 할 수 있지만 대신 고전을 권장합니다. I 매우은 근무일 인 경우 또는 앞으로 리팩터링에 관심이 많을 경우 picking this up을 권장합니다.

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

에라타에 OLI에서 언급 한 바와 같이, 사용자가 설정 할 수 있습니다 32-bit VM 또는 chroot A, 서버가 실행중인 OS에 따라 다릅니다. 이 단지 스팟 문제보다 더 많은 경우 I am adequate, but not an expert in PHP.

  3.

은 위와 같이, 나는 the classics하는 것이 좋습니다. (실제 코드 고정)

  제

우선, 우엑. 논리적으로 논리적으로 캡슐화하지 못한 문서, 주석 크래프트, 복제 논리 및 표현력이없는 변수 이름은 없습니다. 내가 본 최악의 코드는 아니지만 여기서 당신과 공감합니다.

여전히 결과는 이 아닙니다.입니다. 코드베이스에 일련의 단위 테스트가없는 경우 I recommend adding them.

이 기능의 효율성을 벤치마킹하려면 the algorithms defined in the notes here의 결과와 비교하는 것이 좋습니다. 이상적으로 구현 중 하나가 필요합니다. closest to this reference implementation.

스레드의 상단 오프를 도둑질하고 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; 
} 

(. 이것은 당신이 처음에 제공되는 구현과 유사 놀람)

가 왜 $amount을 포함하지 있어요 사양의 일부로? 단순 : 리팩터링하는 코드와 마찬가지로 encapsulation을 위반하지 않습니다. 필요에 따라 ($copya->e[0] & ECC_UPRBIT) ? 1 : 0으로 설정할 수 있습니다.

요약하면 코드를 리팩터링하는 가장 쉬운 방법은 반드시 포함 된 로직을 살펴 보는 것이 아닙니다. 때로는 의도를 결정하고 좋은 참조 구현을 찾는 것이 전부입니다.

+0

+1 위대하고 교육적인 답변, 혹시 선생님이십니까? –

+8

@andreas 아아, 두 개만 생성됩니다. 나는이 글을 쓰는 시점에 겸손한 암 연구자 일 뿐이다. :) – MrGomez

관련 문제