2010-06-30 75 views
0

我試圖從我的服務器上的PHP 5.2.x升級到5.3.2。問題是,我依靠破解執行PHP的ezmlm_hash()(這裏列出的bug是:http://bugs.php.net/bug.php?id=47969)。將C hashing函數轉換爲PHP:ezmlm_hash

我的第一個想法是在PHP中自己重寫本機PHP函數的破碎版本(用C語言編寫),並在我的代碼中使用它,而不是修改PHP源代碼,並且不得不從源代碼編譯PHP。

這裏是代碼的C版:

PHP_FUNCTION(ezmlm_hash) 
{ 
    char *str = NULL; 
    unsigned int h = 5381L; 
    int j, str_len; 

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", 
           &str, &str_len) == FAILURE) { 
     return; 
    } 

    for (j = 0; j < str_len; j++) { 
     h = (h + (h << 5))^(unsigned long) (unsigned char) tolower(str[j]); 
    } 

    h = (h % 53); 

    RETURN_LONG((int) h); 
} 

這裏是我寫在PHP中:

function ezmlm_hash_mine($email_address){ 
    $h = 5381; 
    $email_length = strlen($email_address); 
    for($x=0;$x<$email_length;$x++){ 
     $chr = strtolower($email_address[$x]); 
     $h = ($h + ($h << 5))^(ord($chr)); 
    } 

    $h = $h % 53; 
    return $h; 
} 

我使用一個64位的機器。這兩個函數輸出不同的結果:

$email_addresses = array(
    '[email protected]', 
    '[email protected]', 
); 

print('<PRE>'); 

foreach($email_addresses as $email_address){ 
    print(ezmlm_hash($email_address).PHP_EOL); 
    print(ezmlm_hash_mine($email_address).PHP_EOL.PHP_EOL); 
} 

輸出:

23 
-52 

15 
-21 

我知道我可能有一些精度或打字的問題,我只是不知道如何解決它。任何幫助將不勝感激!

UPDATE

當我運行THES在32臺機器上的代碼,他們兩個輸出新的修正值:

12 
12 

45 
45 

我覺得這事做模運算符..有沒有人知道C模運算符的PHP等價物? PHP中的%表現不同!

更新2

它看起來好像這是不可能的香草PHP,因爲它的浮點運算沒有足夠的精度,古怪英寸我將不得不安裝BCMath或GMP。感謝大家的洞察力。

+0

是你依靠的是什麼行爲?如果是64位的,你不會從你提供的php代碼中得到這個結果,甚至忽略了簽署/未簽名的可能的問題 – Spudd86 2010-06-30 15:51:39

+0

這對我來說絕對是一個64位問題,運行代碼產生相同的結果我的32位機器。 – tplaner 2010-06-30 15:53:25

+0

ezmlm_hash應該使用'unsigned int h = 5381;'而不是'unsigned int h = 5381L;'。這在更高版本的PHP中得到了糾正。即64位版本表現不佳...修復是總是做一個32位計算!所以現在我必須模仿不正確的64位版本... – 2010-06-30 15:54:33

回答

1

試試這個編輯截斷到32位計算後:

function ezmlm_hash_mine($email_address){ 
    $h = gmp_init(5381); 
    $d = gmp_setbit(0, 64); 
    $d32 = gmp_setbit(0, 32); 
    $email_length = strlen($email_address); 

    $chr = strtolower($email_address); 

    for($x=0;$x<$email_length;$x++){  
     $h = gmp_mod(gmp_xor(gmp_mod(gmp_add($h, gmp_mod(gmp_mul($h, "32"), $d)), $d), ord($chr[$x])), $d32); 
    } 

    $h = gmp_mod($h, 53); 
    return gmp_intval($h); 
} 
+0

我沒有安裝GMP,雖然我確信它可以正常工作,但我不想在直接升級之外添加任何內容到我的PHP安裝中。 +1雖然。 – 2010-06-30 16:17:37

+0

不幸的是,我只是試了一下,它有一個錯誤的地方.... – Spudd86 2010-06-30 16:54:13

0

問題可能是在這條線 $ H =($ H +($ H < < 5))^(ORD($ CHR));

在應用xor之前的C中,單個字符被轉換爲4字節長。儘管我不確定什麼類型的退貨,但試着在較小的表達式和測試天氣中打破它們的表達方式,它們在C和PHP中的表現相同。在h和h中應該表現得完全相同, PHP每h。

+0

我認爲這就是php的ord()做了什麼?我應該怎麼做呢? – 2010-06-30 15:36:22

+0

對不起,你可能是對的,你可能想要研究的另一件事是PHP不支持無符號整數,移位操作在有符號和無符號整數上的行爲不同 – Ivan 2010-06-30 15:40:01

+0

這不是轉變,左移與標記和無符號的值,它可能是模數 – Spudd86 2010-06-30 15:46:08