使用错误的值在PHP上移位操作?

时间:2017-09-16 14:46:07

标签: php mysqli bitwise-operators bit-shift phpbb3

我使用phpBB作为论坛平台。我使用的是带有PHP 5.6.31和MySQL(i)5.7.19-log的Mutualised Linux服务器。

而且我发现了一个在其他服务器上没有发生的错误,因为一些phpbb团队成员作为我的一些朋友无法重现这个问题。但是有更多人遇到同样的问题。

对于想要自行检查的人: 基本上全新安装的phpBB 3.2.1,我们可以去ACP - 论坛 - 你的第一个类别 - 你的第一个论坛。 在那里,我们确认了选项"启用快速回复"标记为"否" 然后我们转到ACP - 发布 - 消息 - 发布设置,然后单击"提交并在所有论坛中启用快速回复"。 之后我们再次进入你的第一个论坛"检查"启用快速回复"而它仍然是" No"。 它应该是"是"。

我尝试DEBUG和.php文件,该文件具有将创建将发送到数据库的SQL查询的函数,我已经提出: 印刷(1 <&lt; 6);它给了我64。 所以我也放了:print($ bit);它给了我6。 所以php上的代码(1&lt;&lt;&lt; $ bit)应该是正确的,如果我把:(&lt;&lt;&lt; $ bit);它给了我32!

我已经放了3张照片:

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

结果是:64 6 32

跆拳道?为什么当我们使用6作为值的变量时,它假定为5?!,或者它假定为第6个位置表示一个字节?

任何人都知道为什么会这样吗?也许PHP versin bug?或者任何类型的配置都可以搞乱这个?

让我更好地解释一下。

/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。 这就是$ bit为6的原因。

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

我们可以在这里看到由php代码创建的sql代码。 最后在 /phpbb/db/driver/driver.php 上我们:

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

在那条线之前,我已经放了3张照片,值为64 6 32 ......并且它没有意义,为什么打印$ bit给出6和1&lt;&lt; $ bit给出了32 ...

提前致谢!

1 个答案:

答案 0 :(得分: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(因为像<<这样的按位移位运算符就是这种情况,它可以使用整数参数),但是& #39;不保证。

Float / double值使用起来并不是很安全,最好将round()明确地转换为正确的整数以确保并避免您看到的错误。

$bit = round($bit);

Kudos去@axiac进行事实核查,并推动我写这个作为答案。如果我能进一步改进,请告诉我。