2012-03-25 34 views
10

数年前,我的webhost从32位变为64位,并且一个关键的PHP脚本停止工作。这是由于< <和>>(位移)操作改变了。我能够用rotateleft32和rotateright32更换rotateleft和rotateright例程这样解决我的问题:将复杂的PHP旋转函数转换为64位工作

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位版本的PHP,也许首先运行一个32位虚拟机。 – 2012-03-25 15:41:21

+0

此外,如果您无法进行头对头的比较,您如何知道上面的代码是问题所在? – 2012-03-25 15:42:26

+0

@OliCharlesworth:这是一个有教养的猜测,基于我最初需要的修复和相关的Stackoverflow问题,然后我问:http://stackoverflow.com/questions/397738/32-to-64-bit-gotchas-in -php – lkessler 2012-03-25 15:50:15

回答

26

回答您的问题所有:

虽然我可以详细介绍跟踪和调试过程,但我会推荐经典。我高度推荐picking this up如果这是您的日常工作,或者您未来对重构代码的兴趣超过了。

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

正如勘误提及奥利,你要建立一个32-bit VMchroot,取决于你的服务器运行的是OS。

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

如上,如果这不仅仅是一个点的问题比较多,我建议theclassics

  4. (定影实际的代码)

首先,恶。没有文档,评论cruft,重复的逻辑,以及未能有效封装其逻辑的未表达的变量名称。这不是我见过的最差的代码,但我在这里同情你。

还是,结果不一定是错了。如果您的代码库中没有一系列单元测试,请参阅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伟大而有教育意义的答案,你是否有机会成为老师? – 2012-03-28 01:42:31

+8

@andreas唉,只有他们两个的产卵。在写这篇文章时,我只是一位卑微的癌症研究人员。 :) – MrGomez 2012-03-28 01:45:49