2015-01-14 4 views
0

Я искал разные формы, но не понял, как решить проблему, которая была найдена здесь (first link, second link), но она дала мне ошибка в eval. Я не могу понять, как решить этот код в цикле foreach.Невозможно понять синтаксическую ошибку, неожиданный '=' в eval() 'd code

foreach($_POST as $key => $value) { 
     if(!strstr($key, 'removeFile')){ 
       //initialize variables using eval 
       eval("$" . $key . " = '" . sanitize($value) . "';"); 
     } 
} 
+1

'eval (" \ $ ". $ Key." = '". Sanitize ($ value)."'; ");' Это ** прямо в ответах на первый вопрос, который вы связали **. – sjagr

+5

Запомнить; Eval === Evil –

+1

Это не самый лучший способ, просто используйте массив: '$$ key = sanitize ($ value);' будет лучше. – AbraCadaver

ответ

2

Во-первых, вопросы, я с вашим кодом:

  1. eval очень, очень редко требуется, и крайне опасно, следует использовать с осторожностью. Я развиваюсь в PHP более 10 лет, и никогда действительно столкнулся с ситуацией, которая необходима eval. Это не исключение. Eval не требуется
  2. Вы дезинфицируете весь массив $_POST. Это здорово, но для этого есть специальные функции: filter_input_array, array_filter и многие, многое другое ... не говоря уже о готовых проектах с открытым исходным кодом и фреймворках, которые уже содержат надежный компонент проверки запроса.
  3. Всегда проверяйте возвращаемые значения функций, которые вы, кажется, делать с strstr, но устанут функции, которые возвращают различные типы (как strstr: она возвращает false, если игла не найдена, но возвращает 0, если игла находится в начале строки haystack). Ваш оператор if может не работать должным образом.
  4. Вы принимаете значения sanitize($value), значения не будут содержать ни одной кавычки. Зачем? Потому что если они это сделают, вы в конечном итоге с синтаксической ошибки в вашей evaled строке

Как бы то ни было, вы могли бы легко написать код, используя переменные переменныеи добавить простую проверку чтобы не наступить на существующих переменных в области видимости:

$sanitized = array_filter($_POST, 'sanitize');//call sanitize on all values 
foreach ($sanitized as $key => $value) 
{ 
    if (!isset($$key) && strstr($key, 'removeFile') === false) 
     $$key = $value; 
} 

Но на самом деле, $_POST ценности принадлежат вместе, они являются частью запроса, и должны оставаться сгруппированы ... либо в массиве или в объекте своего рода , Не назначайте каждое значение своей переменной, потому что довольно скоро вы потеряете информацию о том, какие переменные установлены, а какие нет. Использование отключенное переменной создает эту переменную, назначая значение null, так что у вас есть теперь делает для очень к ошибкам кода:

//request 1: POST => id=123&foo=bar 
foreach ($sanitized as $k => $v) 
    $$k = $v; 
$query = 'SELECT x, y, z FROM tbl WHERE id = ?';//using posted ID as value 
$stmt = $db->prepare($query); 
$stmt->execute(array($id)); 

Все хорошо, потому что $id был установлен, но никогда не доверяют сеть, не думайте, что только потому, что $_POST установлен, все ключи будут установлены, и их значения будут правильными:

//request 2: POST => foo=bar&page=2 
foreach ($sanitized as $k => $v) 
    $$k = $v; 
$query = 'SELECT x, y, z FROM tbl WHERE id = ?';//using posted ID as value 
$stmt = $db->prepare($query); 
$stmt->execute(array($id));//id is null 

Теперь у нас есть проблемы. Это всего лишь один пример того, как ваш код может вызвать проблемы. Представьте себе сценарий растет немного, и смотреть на это:

//request 3: POST => id=123&foo=bar&page=2 
foreach ($sanitized as $k => $v) 
    $$k = $v; 
//$id is 123, $foo is bar and $page = 2 
$query = 'SELECT x, y, z FROM tbl WHERE id = ? LIMIT 10';//using posted ID as value 
//a lot more code containing this statement: 
$page = someFunc(); 
$log->write('someFunc returned log: '.$page); 
//more code 
$offset = 10*($page-1);//<-- page is not what we expected it to be 
$query .= sprintf(' OFFSET %d', $offset); 
$stmt = $db->prepare($query); 
$stmt->execute(array($id)); 

Сейчас это может показаться надуманным, и идиотская, но поверьте мне: все эти вещи случиться больше, чем я хочу знать.Добавление некоторого кода, который случайно перезаписывает существующую переменную, которая используется дальше, происходит все время. Особенно в процедурном коде. Не просто слепо распаковать массив. Держите эти одну переменные и использовать ключи, чтобы избежать:

  • седым волосам
  • внезапно, драматично облысением
  • потери здравомыслия
  • кровоточащей язвы
  • В рабочей среде: катастрофические потери данных
  • Внезапная потеря работы
  • ... так как такой код заставляет единорогов плакать, а bronies wi ll hunt you down
+0

сделанный вашим логика спасибо – user3833682

+0

@ user3833682: Рад, что я мог бы помочь. Если в моем ответе были исправлены ваши проблемы, [пожалуйста, примите ответ] (http://meta.stackexchange.com/a/5235/187465) –

+0

@ user3833682: подумайте о принятии этого ответа. Для этого нажмите отметку в левой части ответа, чтобы она стала зеленой. Вот как мы отмечаем вопросы, разрешенные здесь, и это вознаграждает помощника немного за их усилия. – halfer

1

Как первый ответ на сообщение, с которым вы связались, проблема в том, что при использовании двойных кавычек PHP думает, что ваш код eval() начинается с переменной. Поскольку это не так, у вас есть два варианта. Используйте одинарные кавычки и не забывайте избегать одиночных кавычек, объявляющих строку в коде или избегая знака доллара.

Bonus нота

Там существуют более изящные решения проблемы, которую вы пытаетесь решить. Лучшее решение, о котором я могу думать, это использовать функцию extract. Это дает два основных преимущества.

  1. Он работает со всеми ассоциативными массивами
  2. Вы можете указать различные флаги, которые могут помочь вам отличить распакованные переменный друг от друга и избежать переменной инъекции.

Один флаг, который вы можете использовать, - EXTR_PREFIX_ALL. Это префикс всех выделенных переменных с вашим собственным префиксом. Затем вы должны получить доступ к переменным с префиксом «PREFIX_» как следующее:

$array = [ 
    'variable1' => 'foo', 
    'variable2' => 'bar' 
]; 

extract($array, EXTR_PREFIX_ALL, 'PREFIX_'); 

$value1 = $PREFIX_variable1; // Equals: foo 
$value2 = $PREFIX_variable2; // Equals: bar 

Немного о инъекции кода

Предположим, у вас есть код:

$login = false; 

$login переменная определяет, зарегистрирован ли пользователь или нет. Затем вы используете функцию'extract 'с массивом следующих без использования каких-либо флагов.

$array = [ 
    'login' => true, 
    'foo' => 'bar' 
]; 

extract($array); 

Теперь ваша переменная $login будет установлен true и пользователь размещения данных бы переписаны начальную установку и получили доступ к веб-сайту без действительного входа в систему. Имейте в виду, что это более упрощенный пример, но, тем не менее, действительный.

Чтобы преодолеть это, вы можете использовать флаг EXTR_SKIP или префикс их, как я ранее показывал. Флаг EXTR_SKIP пропустит элемент массива, если определена переменная с тем же именем. Итак, теперь ваш код не будет перезаписывать переменную $login.

extract($array, EXTR_SKIP); // Skip existing variables 
// Or 
extract($array, EXTR_PREFIX_ALL, 'prefix'); // Prefix them all. 

Надеюсь, это поможет вам выбрать правильный вариант для ваших нужд.

С уважением.

Смежные вопросы