Pull to refresh

Особенности условных конструкции со строками в PHP

Reading time3 min
Views3.4K
На Хабре часто обсуждается какой язык лучше для написания безопасных приложений. При этом часто отмечается, что PHP спроектирован таким образом, что начинающий разработчик будет допускать ошибки, приводящие к дырам безопасности. В этом хабрапосте я хочу рассказать о, на мой взгляд, нелогичном поведении операций сравнения, операторов if и switch при работе со строками. Опытным разработчикам данные особенности известны, но решил все же собрать их в одном месте. Думаю пост будет полезен начинающим разработчикам и тем, кто работает в PHP, имея опыт программирования на других языках.

Что есть истина?

Какие строки истинны? Рассмотрим пример:
echo '"" is '. (''?'true':'false'). "\n";
echo '«0» is '. ('0'?'true':'false'). "\n";
echo '"-0" is '. ('-0'?'true':'false'). "\n";
echo '«0.0» is '. ('0.0'?'true':'false'). "\n";
echo '«00» is '. ('00'?'true':'false'). "\n";
echo '«A» is '. ('A'?'true':'false'). "\n";Имеем:"" is false
«0» is false
"-0" is true
«0.0» is true
«00» is true
«A» is true
Итак истинны все непустые строки, кроме строки «0». Логика такого поведения для меня не ясна. На практике часто с помощью оператора if проверяется заполнено ли поле формы, например:if(isset($_GET['income']) && $_GET['income']) {… }Такая проверка примет поле, в котором указан 0 за незаполненное. Чтобы избежать возможного недоразумения, следует использовать проверку в виде: if(isset($_GET['income']) && strlen($_GET['income'])) {… }

Сравнение с участием строк

В PHP два оператора сравнения == и ===. Второй оператор сравнивает совпадение типов и значений, первый производит преобразование типа, а затем выполняет сравнение. Особенность оператора == в том, что при сравнении числа и строки, просходит преобразование строки в число. Если строка не представляет собой число, то она преобразуется в числовое значение 0. Рассмотрим пример:echo '«A»==0 is '. ('A'==0?'true':'false'). "\n";
echo '«A»===0 is '. ('A'===0?'true':'false'). "\n";
echo '«A»==0.0 is '. ('A'==0?'true':'false'). "\n";
echo '«A»===0.0 is '. ('A'===0?'true':'false'). "\n";Результат работы скрипта:«A»==0 is true
«A»===0 is false
«A»==0.0 is true
«A»===0.0 is falseЕсли ваша функция сравнивает строку, переданную в качестве аргумента с заданной строкой, то следует предварительно проверить, что в качестве аргумента передана строка, а не число. Пример будет приведен далее, при рассмотрении оператора switch.

Оператор switch

Мы ожидаем, что оператор switch сравнивает переданное значение с заданными константами. Особенность реализации switch в php в том, что он производит сравнение с помощью оператора ==, то есть не производит сравнение типов. В качестве примера рассмотрим вымышленную функцию, которая возвращает зарплату сотрудника, получая его имя на входе:<?php
function get_salary($name) {
switch($name) {
case 'John':
return 3400;
break;
case 'Mary':
return 4600;
break;
default:
return 0;
}
}

echo «John's salary is ». get_salary('John'). "\n";
echo «Mary's salary is ». get_salary('Mary'). "\n";
echo «Peter's salary is ». get_salary('Peter'). "\n";
echo «0's salary is ». get_salary(0). "\n";
?>Результат работы скрипта:John's salary is 3400
Mary's salary is 4600
Peter's salary is 0
0's salary is 3400На примере видно, что безопасность функции скомпрометирована путем передачи числового значения вместо строкового. Чтобы защитить функцию от нежелательного использования, требуется проверять тип входного значения.<?php
function get_salary($name) {
if(!is_string($name)) return 0;
switch($name) {
case 'John':
return 3400;
break;
case 'Mary':
return 4600;
break;
default:
return 0;
}
}

echo «John's salary is ». get_salary('John'). "\n";
echo «Mary's salary is ». get_salary('Mary'). "\n";
echo «Peter's salary is ». get_salary('Peter'). "\n";
echo «0's salary is ». get_salary(0). "\n";
?>Результат работы скрипта:John's salary is 3400
Mary's salary is 4600
Peter's salary is 0
0's salary is 0Итак, некоторые операции сравнения ведут себя контринтуитивно. Кто предупрежден, тот вооружен.

Кросспост Особенности условных конструкции со строками в PHP с webew.ru.
Tags:
Hubs:
Total votes 45: ↑42 and ↓3+39
Comments88

Articles