您的位置 首页 php

Phper学C兴趣入门-为什么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字符。

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。到这里上面的长度计算想必大家都弄明白了吧。

这里再留个大家一个思考题,strlen和mb_strlen有什么区别?

有兴趣的可以看看我这篇博客

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");
 

案例来源:

在线执行结果

可以看出来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 函数是官方手册在线说明了的非二进制安全的函数。

课后思考

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

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

作者:周梦康

本文为云栖社区内容,未经允许不得转载。

文章来源:智云一二三科技

文章标题:Phper学C兴趣入门-为什么php手册里说某个字符串函数是二进制安全

文章地址:https://www.zhihuclub.com/79753.shtml

关于作者: 智云科技

热门文章

网站地图