mysqli — операция сдвига бит на PHP с неправильными значениями?

Я использую phpBB в качестве платформы форума. Я использую сервер Mutualised Linux с PHP версии 5.6.31 и MySQL (i) 5.7.19-log.

И я обнаружил ошибку, которая не возникает на других серверах, поскольку некоторые члены команды phpbb, как и мой друг, не могли воспроизвести проблему. Но есть больше людей с той же проблемой.

Для людей, которые хотят проверить сами:
В основном с новой установкой phpBB 3.2.1 мы можем перейти на ACP — Forums — Ваша первая категория — Ваш первый форум.
Там мы подтвердили, что опция «Включить быстрый ответ» помечена как «Нет». Затем мы переходим к ACP — Отправка сообщений — Настройки сообщений и нажимаем «Отправить и включить быстрый ответ на всех форумах».
После этого мы снова идем на «ваш первый форум», чтобы проверить «Включить быстрый ответ» и он по-прежнему отображается как «Нет».
И это должно быть «Да».

Я попытался отладить и .php-файл, который имеет функцию, которая будет создавать запрос SQL, который будет отправлен в базу данных, я поставил:
печать (1 << 6); и это дает мне 64.
Так что я тоже поставил: print ($ bit); и это дает мне 6.
Итак, код (1 << $ bit), который находится на php, должен быть правильным и должен дать мне 64 НО, если я поставлю: print (1 << $ Бит); это дает мне 32!

Я поставил 3 отпечатка:

print(1 << 6);
print($bit);
print(1 << $bit);

И результат был: 64 6 32

Wtf ?! Какого черта, когда у нас есть переменная со значением 6, она принимает значение 5?!, Или она принимает в качестве 6-й позиции представление байта?

У кого-нибудь есть идеи, почему это происходит? Может быть PHP баг версии? Или любой тип конфигурации может связываться с этим?

Позвольте мне объяснить лучше.

В /includes/constants.php мы можем найти:
define('FORUM_FLAG_QUICK_REPLY', 64);
Это значение будет использоваться для создания значения $ bit.

И на /includes/acp/acp_board.php у нас есть функция, которая создаст переменную $ bit:

$config->set($config_name, $config_value);
if ($config_name == 'allow_quick_reply' && isset($_POST['allow_quick_reply_enable']))
{
enable_bitfield_column_flag(FORUMS_TABLE, 'forum_flags', log(FORUM_FLAG_QUICK_REPLY, 2));
}

Эта функция _enable_bitfield_column_flag_ создаст SQL-код.
И журнал (FORUM_FLAG_QUICK_REPLY, 2) = Log2 (64) = 6.
Вот почему бит $ равен 6.

И в включает / functions_admin.php мы в:

function enable_bitfield_column_flag($table_name, $column_name, $flag, $sql_more = '')
{
global $db;
$sql = 'UPDATE ' . $table_name . '
SET ' . $column_name . ' = ' . $db->sql_bit_or($column_name, $flag) . '
' . $sql_more;
$db->sql_query($sql);
}

Мы можем увидеть здесь SQL-код, созданный с помощью PHP-кода.
И наконец на /phpbb/db/driver/driver.php мы в:

return $column_name . ' | ' . (1 << $bit) . (($compare) ? ' ' . $compare : '');

И перед этой строкой я поставил 3 отпечатка, и значения были 64 6 32 … и не имеет смысла, почему print $ bit дает 6 и 1 << $ bit дает 32 …

Заранее спасибо!

1

Решение

Основываясь на наших комментариях, и предположим, что $ bit действительно log2(64)Я провел несколько тестов и подтвердил свою первоначальную идею:

$bit = log(64,2);
echo gettype(6)."\n"; //  integer
echo gettype($bit)."\n"; //  double
echo (int)$bit."\n"; // prints 6, but might as well have been 5
echo round($bit)."\n"; // prints 6

демо здесь: https://3v4l.org/Zogme

В этой демонстрации все проверенные версии php приводят к приведению результата к 6 при преобразовании в целочисленный тип (как в случае с побитовыми операторами сдвига, такими как <<, который работает с целочисленными аргументами), но это не гарантировано.

Значения с плавающей запятой / double не очень безопасны для работы, лучше округляйте их явно до целого числа, просто чтобы быть уверенным и избежать ошибки, которую вы видите.

$bit = round($bit);

Престижность идет к @axiac для проверки фактов и подталкивает меня написать это как ответ. Дайте мне знать, если я смогу улучшить его.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]