내가 PHP로 개발해온 모든 해 동안, 나는 항상 사용하는 eval()
것이 악 하다고 들었습니다 .
다음 코드를 고려할 때 두 번째 (더 우아한) 옵션을 사용하는 것이 합리적이지 않습니까? 그렇지 않다면 왜?
// $type is the result of an SQL statement
// e.g. SHOW COLUMNS FROM a_table LIKE 'a_column';
// hence you can be pretty sure about the consistency
// of your string
$type = "enum('a','b','c')";
// possibility one
$type_1 = preg_replace('#^enum\s*\(\s*\'|\'\s*\)\s*$#', '', $type);
$result = preg_split('#\'\s*,\s*\'#', $type_1);
// possibility two
eval('$result = '.preg_replace('#^enum#','array', $type).';');
답변
eval () 순수한 악을 호출 할 때는주의해야합니다. 동적 평가는 강력한 도구이며 때로는 생명의 은인이 될 수 있습니다. eval ()을 사용하면 PHP의 단점을 해결할 수 있습니다 (아래 참조).
eval ()의 주요 문제점은 다음과 같습니다.
- 잠재적으로 안전하지 않은 입력. 신뢰할 수없는 매개 변수를 전달하는 것은 실패하는 방법입니다. 매개 변수 (또는 매개 변수의 일부)가 완전히 신뢰할 수 있는지 확인하는 것은 종종 간단한 작업이 아닙니다.
- 속임수. eval ()을 사용하면 코드가 영리 해져 따라 가기가 더 어려워집니다. Brian Kernighan을 인용하려면 ” 디버깅은 처음에 코드를 작성하는 것보다 두 배 더 어렵습니다. 따라서 코드를 가능한 한 똑똑하게 작성하면 정의상 디버깅 할만큼 똑똑하지 않은 것입니다. “
eval ()의 실제 사용과 관련된 주요 문제는 다음 중 하나입니다.
- 충분히 고려하지 않고 사용하는 경험이없는 개발자.
경험상 나는 이것을 따르는 경향이 있습니다.
- 때로는 eval ()이 유일한 / 올바른 솔루션입니다.
- 대부분의 경우 다른 것을 시도해야합니다.
- 확실하지 않은 경우 2로 이동합니다.
- 그렇지 않으면 매우 조심하십시오.
답변
평가 된 문자열에 userinput이 포함될 가능성이 아주 적을 때 eval은 악의적입니다. 사용자의 콘텐츠없이 평가를 할 때 안전해야합니다.
그럼에도 불구하고 eval을 사용하기 전에 최소한 두 번 생각해야합니다. 믿을 수 없을 정도로 간단 해 보이지만 오류 처리 (VBAssassins 주석 참조), 디버깅 가능성 등을 염두에두고 더 이상 간단하지 않습니다.
따라서 경험 상으로는 잊어 버리세요. eval이 대답이면 잘못된 질문을하는 것입니다! 😉
답변
eval ()은 항상 똑같이 악합니다.
“eval ()은 언제 악하지 않습니까?” eval () 사용의 단점이 일부 상황에서 마술처럼 사라진다는 것을 암시하는 것처럼 보이기 때문에 내 의견으로는 잘못된 질문입니다.
eval ()을 사용하면 일반적으로 코드의 가독성, 런타임 전에 코드 경로 (및 그에 대한 가능한 보안 영향)를 예측할 수있는 기능, 따라서 코드 디버그 기능이 저하되기 때문에 일반적으로 나쁜 생각입니다. eval ()을 사용하면 평가 된 코드와이를 둘러싼 코드가 PHP 5.5 이상에 통합 된 Zend Opcache와 같은 opcode 캐시 나 HHVM에있는 것과 같은 JIT 컴파일러에 의해 최적화되는 것을 방지 할 수 있습니다.
게다가 eval ()을 반드시 사용해야하는 상황은 없습니다. PHP는 그것 없이는 완전한 기능을 갖춘 프로그래밍 언어입니다.
실제로 이것을 악으로 보는지 아닌지 또는 경우에 따라 eval ()을 사용하여 개인적으로 정당화 할 수 있는지 여부는 귀하에게 달려 있습니다. 어떤 사람들에게는 악이 너무 커서 그것을 정당화 할 수없고 다른 사람들에게는 eval ()이 편리한 지름길입니다.
그러나 eval ()을 악하다고 생각하면 항상 악합니다. 문맥에 따라 마법처럼 악을 잃지 않습니다.
답변
이 경우 사용자가 테이블에 임의의 열을 생성 할 수없는 한 eval은 충분히 안전 할 수 있습니다.
그래도 더 이상 우아하지는 않습니다. 이것은 기본적으로 텍스트 구문 분석 문제이며 처리하기 위해 PHP의 구문 분석기를 남용하는 것은 약간 엉망인 것처럼 보입니다. 언어 기능을 남용하려면 JSON 파서를 남용하지 않는 이유는 무엇입니까? 적어도 JSON 파서에서는 코드 삽입의 가능성이 전혀 없습니다.
$json = str_replace(array(
'enum', '(', ')', "'"), array)
'', '[', ']', "'"), $type);
$result = json_decode($json);
정규식이 아마도 가장 확실한 방법 일 것입니다. 단일 정규식을 사용하여이 문자열에서 모든 값을 추출 할 수 있습니다.
$extract_regex = '/
(?<=,|enum\() # Match strings that follow either a comma, or the string "enum("...
\' # ...then the opening quote mark...
(.*?) # ...and capture anything...
\' # ...up to the closing quote mark...
/x';
preg_match_all($extract_regex, $type, $matches);
$result = $matches[1];
답변
eval()
느리지 만 나는 그것을 악이라고 부르지 않을 것입니다.
코드 삽입으로 이어질 수 있고 악할 수있는 것은 우리가 만드는 나쁜 사용 입니다.
간단한 예 :
$_GET = 'echo 5 + 5 * 2;';
eval($_GET); // 15
해로운 예 :
$_GET = 'system("reboot");';
eval($_GET); // oops
사용하지 않는 것이 eval()
좋지만 사용하는 경우 모든 입력의 유효성을 검사 / 허용하도록하십시오.
답변
eval 내에서 외부 데이터 (예 : 사용자 입력)를 사용하는 경우.
위의 예에서 이것은 문제가 아닙니다.
답변
여기서 콘텐츠를 노골적으로 훔칠 것입니다.
본질적으로 평가는 항상 보안 문제가 될 것입니다.
보안 문제 외에도 eval에는 믿을 수 없을 정도로 느린 문제도 있습니다. PHP 4.3.10에서 테스트 한 결과 일반 코드보다 10 배 느리고 PHP 5.1 베타 1에서는 28 배 느립니다.