如何解决ip2long("012.012.012.012") 在 Linux 上返回 false
假设 IPv4 地址表示中有前导零,例如 012.012.012.012
。
为了抑制前导零,我简单地编写了以下代码,它在我的 Mac 上按我的预期工作:
% PHP -r 'var_dump(long2ip(ip2long("012.012.012.012")));'
Command line code:1:
string(11) "12.12.12.12"
% PHP --version
PHP 7.3.25 (cli) (built: Dec 25 2020 22:03:38) ( NTS )
copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.25,copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.3.25,copyright (c) 1999-2018,by Zend Technologies
with Xdebug v3.0.1,copyright (c) 2002-2020,by Derick Rethans
但是这段简单的代码在 CentOS 7 上不起作用,似乎 ip2long("012.012.012.012")
返回 false
值:
$ PHP -r 'var_dump(long2ip(ip2long("012.012.012.012")));'
string(7) "0.0.0.0"
$ PHP --version
PHP 7.3.25 (cli) (built: Nov 24 2020 11:10:55) ( NTS )
copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.25,copyright (c) 1998-2018 Zend Technologies
$ cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)
两个 PHP 版本是相同的,我希望它们返回完全相同的值。我还阅读了 ip2long docs 并尝试查找此行为是否有任何特殊选项/配置,但没有运气。
有人能把我引向正确的方向吗? 是什么让他们与众不同?我该怎么办?
解决方法
好的,我找到了罪魁祸首。 LLVM 和 GCC 之间 inet_pton(3)
的不同实现导致了这种行为,如 Russ-san commented。 6 年前有a bug report 完全相同的问题。根据 this patch,PHP v5.2.10 似乎已经开始使用 inet_pton
而不是 inet_addr
,这就是 older versions of PHP 将每个块视为八进制的原因。
test.c
#include <stdio.h>
#include <arpa/inet.h>
#define INADDR "012.012.012.012"
int main() {
struct in_addr inaddr;
if (inet_pton(AF_INET,INADDR,&inaddr) == 0) {
printf("Invalid: %s\n",INADDR);
}
else {
printf("Valid: %s\n",INADDR);
}
return 0;
}
- 苹果
% cc test.cc && ./a.out
Valid: 012.012.012.012
- Linux
$ cc test.cc && ./a.out
Invalid: 012.012.012.012
我放弃使用 ip2long
/ long2ip
内置函数,现在尝试使用 https://github.com/mlocati/ip-lib
>>> \IPLib\Address\IPv4::fromString("1.2.3.12")->toString(true);
=> "001.002.003.012"
>>> \IPLib\Address\IPv4::fromString("001.002.003.012")->toString();
=> "1.2.3.12"
目前没有问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。