strcmp返回整数而非布尔值,直接用于if判断会导致逻辑反转:相等时返回0(false)被跳过,不等时返回非零(true)反而执行;正确写法是if (strcmp($a, $b) === 0)或$a === $b。

strcmp 返回值不是布尔值,直接用于 if 判断会翻车
很多人写 if (strcmp($a, $b)) 想表达“不相等就执行”,但 strcmp 实际返回的是整数:相等时为 0,不等时为负数或正数。而 PHP 中 0 在布尔上下文里是 false,非零才是 true —— 所以这个条件恰恰在“相等时跳过、不等时进入”,逻辑完全反了。
常见错误场景:
- 遍历
$_GET参数匹配键名时用strcmp($key, "page")做判断,结果"page"一出现就因返回0被跳过 - 写成
if (!strcmp($a, $b))才是对的,但可读性差,且容易漏掉取反 - 更安全的写法是显式判断:
if (strcmp($a, $b) === 0)或直接用$a === $b
== 松散比较会触发隐式类型转换,结果不可控
PHP 遇到 == 就会尝试把两边转成同一类型再比。比如 "0e123" == "0e456" 会被当作两个科学计数法数字,都转成浮点数 0.0,结果为 true;"1abc" == 1 会把字符串截出开头数字 1,也判为 true。
典型陷阱:
-
0 == "abc"→true(字符串转整数为0) -
"000" == 0→true(字符串转整数为0) -
NULL == false、array() == false全都为true,但NULL === false是false - 表单传来的所有值本质都是字符串,和整数或布尔做
==极易误判
switch 和 in_array 默认走松散比较,case 匹配可能意外命中
switch 对输入值不做类型校验,只做 == 级别比较。传入字符串 "1abc",会转成整数 1,然后匹配到 case 1:;传入空数组 [],转成 0,可能匹配到 case 0:。
in_array() 同理,默认也是松散比较:
-
in_array("1", [1, 2, 3])返回true(字符串"1"被转成整数1) - 正确做法是加第三个参数:
in_array("1", [1, 2, 3], true) -
switch无法强制严格比较,只能自己先做类型检查,或改用if/elseif+===
函数参数传数组却没校验,strcmp/md5 返回意外值
当用户恶意提交 password[]=123,$_GET['password'] 就变成数组。此时调用 strcmp($_GET['password'], 'abc'),PHP 会把数组转成字符串 "Array" 再比较 —— 但实际行为是:只要任一参数是数组,strcmp 直接返回 0(PHP 内部处理逻辑)。同理,md5([]) 返回 null,md5([]) == md5([]) 就成了 null == null → true。
这类问题在 CTF 或真实业务中常被利用绕过验证:
- 不要假设输入一定是字符串,用
is_string()或filter_var()提前校验 - 对关键参数(如 token、密码、ID)一律用
===和is_string()双重防护 - 避免在安全逻辑里依赖
strcmp或md5的返回值做分支,优先用hash_equals()做恒定时间比较
最麻烦的不是某一行写错,而是弱类型转换发生在底层、不可见、跨函数调用。一个 == 引发的 bug,可能要追三四个函数才能定位到源头类型是怎么丢的。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











