我試圖從我的服務器上的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。感謝大家的洞察力。
是你依靠的是什麼行爲?如果是64位的,你不會從你提供的php代碼中得到這個結果,甚至忽略了簽署/未簽名的可能的問題 – Spudd86 2010-06-30 15:51:39
這對我來說絕對是一個64位問題,運行代碼產生相同的結果我的32位機器。 – tplaner 2010-06-30 15:53:25
ezmlm_hash應該使用'unsigned int h = 5381;'而不是'unsigned int h = 5381L;'。這在更高版本的PHP中得到了糾正。即64位版本表現不佳...修復是總是做一個32位計算!所以現在我必須模仿不正確的64位版本... – 2010-06-30 15:54:33