Phper 学 C 兴趣入门 - 为什么 php 手册里经常说某个字符串函数是二进制安全的-阿里云开发者社区

开发者社区> 周梦康> 正文

Phper 学 C 兴趣入门 - 为什么 php 手册里经常说某个字符串函数是二进制安全的

简介: 为什么 php 手册里经常说某个字符串函数是二进制安全的
+关注继续查看

引子

为什么 php 手册里经常说某个函数是二进制安全的?我们平常使用函数的时候也没发现有什么区别呀,那么二进制安全到底是什么意思呢?

Php 实验

<?php
echo strlen("abc"); // 3
echo strlen("abc\0"); // 4
echo strlen("abc\0d"); // 5
echo strlen("abc\0def"); // 7

从上面的规律可以看出\0被认为是一个字符,其实在上面的式子中\0是一个ascii字符。

补课简单说明下 ascii 码

我们知道,计算机内部,所有信息最终都是一个二进制值。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从0000000011111111

上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码,一直沿用至今。

man ascii

ascii 码前 33 个都是控制字符,比如我们最熟悉的换行,都是不可见的字符。

       Oct   Dec   Hex   Char                        Oct   Dec   Hex   Char
       ────────────────────────────────────────────────────────────────────────
       000   0     00    NUL '\0'                    100   64    40    @
       001   1     01    SOH (start of heading)      101   65    41    A
       002   2     02    STX (start of text)         102   66    42    B
       003   3     03    ETX (end of text)           103   67    43    C
       004   4     04    EOT (end of transmission)   104   68    44    D
       005   5     05    ENQ (enquiry)               105   69    45    E
       006   6     06    ACK (acknowledge)           106   70    46    F
       007   7     07    BEL '\a' (bell)             107   71    47    G
       010   8     08    BS  '\b' (backspace)        110   72    48    H
       011   9     09    HT  '\t' (horizontal tab)   111   73    49    I
       012   10    0A    LF  '\n' (new line)         112   74    4A    J

从上面的表中可以看到八进制012和十六进制0A都表示换行

echo "abc\012d";
echo "\n";
echo "abc\x0Ad";
echo "\n";
echo "abc\x0ad";
echo "\n";
echo "abc\nd";
echo "\n";

输出结果

abc
d
abc
d
abc
d
abc
d

ascii 码第一个\0则表示空字符,所以执行

echo "abc\0d"; 

输出的就是abcd。到这里上面的长度计算想必大家都弄明白了吧。

这里再留个大家一个思考题,strlenmb_strlen有什么区别?
有兴趣的可以看看我这篇博客 https://mengkang.net/1129.html

C 实验

#include <stdio.h>
#include <string.h>

int main(){
    printf("%d\n",strlen("abc")); // 3
    printf("%d\n",strlen("abc\0")); // 3
    printf("%d\n",strlen("abc\0d")); // 3
    printf("%d\n",strlen("abc\0def")); // 3
}

通过上面的例子可以观察到\0及其以后都不在strlen的计算范围内。在C语言里字符串都以\0作为结束符。

#include <stdio.h>
#include <string.h>

int main(){
    printf("%s\n","abc\0def"); // abc
}

所以,因为字符串中间有\0而影响程序逻辑和结果的情况,叫非二进制安全。

思考

通过上面的两个实验发现只有C里面我们才需要关注函数的二进制安全问题嘛,PHP 也会遇到类似的问题么?我怎么从来遇到过。下面两个例子。

案例1

<?php
echo date("Y\0/m/d");

案例来源:https://stackoverflow.com/questions/36933837/why-are-there-binary-safe-and-binary-unsafe-functions-in-php

在线执行结果 https://3v4l.org/dqXhf

image.png

可以看出来date函数是把入参"0/m/d"去掉了,不过在 php7 里修复了该问题。

案例2

<?php
var_export(strcoll("a\0b","a"));
var_export(strcmp("a\0b","a"));

这两个函数都是比较字符串“大小”,strcoll 会根据环境变量 LC_COLLATE 所指定的文字排列次序来比较两字符串的大小,默认 LC_COLLATE 为"POSIX"或"C",strcoll() 和 strcmp() 一样根据ASCII比较字符串大小。

strcoll 函数是官方手册在线说明了的非二进制安全的函数。https://www.php.net/manual/en/function.strcoll.php

课后思考

下面这个两个计算长度分辨是多少,下次课我们一起分析 php 和 c 里面单引号和双引号的区别。

<?php
echo strlen("123\0456");
echo strlen('123\0456');

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
如何在函数计算中使用 Node.js 处理 multipart 文件上传请求
web 开发中我们经常会允许用户通过 HTTP POST 请求上传文档到服务器,本文将介绍在函数计算中基于 node.js 使用 multipart form-data 来实现文件上传服务。
2709 0
【Boost】boost库asio详解2——io_service::run函数无任务时退出的问题
io_service::work类可以使io_service::run函数在没有任务的时候仍然不返回,直至work对象被销毁。 [cpp] view plain copy    print? void test_asio_nowork()   {       b...
1195 0
【评论】为什么PHP比Ruby更加实用?
导读:作者Bastien用风趣的口吻写了一篇文章《Why PHP is (so much) better than Ruby?》,作者实际并不是认为PHP比Ruby好,只是用不同的方式表现出Ruby的薄弱之处。
846 0
获取sql server与年、季度、月、周首尾有关的时间函数
--当前日期: 2013-12-31 select convert(varchar(10), getdate(),120) --当前日期+ 时间:2013-12-31 14:36:46.860 select getdate() --一个月的第一天:2013-12-31 00:00:00.000 select dateadd(mm,datediff(mm,0,getd
1900 0
lua二进制操作函数
  由于 Lua 脚本语言本身不支持对数字的二进制操作(例如 与,或,非 等操作),MUSHclient 为此提供了一套专门用于二进制操作的函数,它们都定义在一个“bit”表中,使用时只要requre “bit”即可。
993 0
+关注
周梦康
十年前从 LNMP 开始个人站长 mengkang.net 生涯。 分享各种线上故障复盘笔记,关注我,防止采坑。
116
文章
70
问答
来源圈子
更多
PHP学习资料大全
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载