문제

나는 사용하고있다 eval 루비의 특징은 여러 번. 그러나 나는 사람들이 말하는 것을 들었습니다 evalS는 불쾌합니다. 물었을 때, 왜 그리고 어떻게, 나는 그것을 사용하지 않는 설득력있는 이유를 결코 얻을 수 없었습니다. 그들은 정말로 불쾌합니까? 그렇다면 어떤 식으로? 평가할 "안전한"옵션은 무엇입니까?

도움이 되었습니까?

해결책

당신이있는 경우 eval사용자가 제출하거나 수정할 수있는 문자열은 임의의 코드 실행을 허용하는 것과 관련이 있습니다. 문자열에 OS 호출이 포함되어 있다고 상상해보십시오 rm -rf / 또는 유사합니다. 즉, 문자열이 적절하게 제한되어 있거나 Ruby 통역사가 적절하게 또는 이상적으로 샌드 박스를 알고있는 상황에서 eval 매우 강력 할 수 있습니다.

문제는 유사합니다 SQL 주입, 당신이 친숙하다면. 여기서의 솔루션은 주입 문제 (매개 변수화 쿼리)에 대한 솔루션과 유사합니다. 즉, 당신이 원하는 진술이라면 eval 매우 구체적인 형태로 알려져 있으며 모두 명세서 중 몇 가지 변수, 수학 표현식 또는 이와 유사한 성명서를 제출해야합니다. 사용자로부터 이러한 작은 부분을 가져 가서 필요한 경우 소독한 다음 사용자 입력을 포함하여 안전한 템플릿 문을 평가할 수 있습니다. 적절한 장소에서.

다른 팁

루비에는 eval():

  1. 거기 있습니다 #send 문자열로 이름이있는 메소드를 호출하고 매개 변수를 전달할 수 있습니다.
  2. yield 코드 블록을 수신 방법의 맥락에서 실행되는 메소드로 전달할 수 있습니다.
  3. 종종 단순한 Kernel.const_get("String") 이름이 문자열로있는 클래스를 얻기에 충분합니다.

나는 그것들을 올바르게 설명 할 수 없다고 생각한다.

eval 다른 곳에서 지적 된 것처럼 불안한 일뿐 만 아니라 느리지 만 느린다. 그것이 실행 될 때마다 evalED 코드를 구문 분석해야합니다 (예 : Jruby의 경우 Bytecode로 전환)은 다음과 같습니다. eval 많은 것들이 많고 통역사의 해당 부분은 크고 큰 것 외에도 캐시 차량입니다).

왜 거기있어 eval 루비에서 전혀 물어보세요? "우리는"대부분 - 실제로 eval (LISP 프로그래밍 언어를 위해) 발명되었습니다. 대부분 쇼를 위해! 더 많은 것을 사용합니다 eval 전처리 서기, 디버거 또는 템플릿 엔진 쓰기와 같은 메타 프로 그램 작업을 위해 "통역사에 통역사 추가"를 원할 때 옳은 일입니다. 그러한 응용 프로그램에 대한 일반적인 아이디어는 루비 코드를 마사지하고 eval 그것에, 그리고 그것은 확실히 도메인 별 장난감 언어를 재창조하고 구현하는 것을 이겼습니다. Greenspun의 열 번째 규칙. 경고는 다음과 같습니다. 예를 들어 템플릿 엔진의 경우 비용을 조심하십시오. eval시작 시간에 실행되지 않음; 그리고하지 마십시오 eval 신뢰할 수없는 코드는 "길들인"방법을 알지 않는 한, 즉 이론에 따라 언어의 안전한 하위 집합을 선택하고 시행합니다. 능력 규율. 후자는 a 많은 정말 어려운 일의 (예 : 참조 Java를 위해 어떻게 이루어 졌는지; 나는 불행히도 루비에 대한 그러한 노력을 모른다).

디버깅을 어렵게 만듭니다. 최적화가 어렵습니다. 그러나 무엇보다도, 그것은 일반적으로 당신이하려는 모든 일을하는 더 좋은 방법이 있다는 신호입니다.

당신이 우리에게 무엇을 달성하고자하는지 말해 주면 eval, 특정 시나리오와 관련된 관련 답변을 얻을 수 있습니다.

Eval은 신중하게 사용해야하는 엄청나게 강력한 기능입니다. Matt J가 지적한 보안 문제 외에도 디버깅 런타임 평가 코드가 매우 어렵다는 것을 알게 될 것입니다. 런타임 평가 코드 블록의 문제는 통역사가 표현하기가 어렵습니다. 따라서 찾는 것은 어려울 것입니다.

즉, 그 문제에 익숙하고 보안 문제에 대해 걱정하지 않는다면 루비를 그대로 매력적으로 만드는 기능 중 하나를 사용하지 않아야합니다.

특정 상황에서는 잘 배치됩니다 eval 영리하고 필요한 코드의 양을 줄입니다. Matt J가 언급 한 보안 문제 외에도 매우 간단한 질문을해야합니다.

모든 것이 말하고 끝났을 때, 다른 사람이 코드를 읽고 자신이 한 일을 이해할 수 있습니까?

대답이 아니오라면, 당신이 얻은 것은 eval 유지 보수에 대한 버려진다. 이 문제는 팀에서 일하는 경우에도 적용 할 수있을뿐만 아니라 귀하에게도 적용 할 수 있습니다. 지금부터 몇 년이 아닌 코드 개월을 되돌아보고 자신이 한 일을 알고 싶어합니다.

"외부"에서 eval, 당신은 뭔가 잘못하고 있고 매우 불쾌합니다. 이것의 매우 코드가 안전 할 정도로 충분히 탈출하기 어렵 기 때문에 매우 안전하지 않다고 생각합니다. 그러나 다음 코드 예제와 같이 복제 또는 기타 유사한 것들을 피하기 위해 Eval을 사용하는 경우 사용해도 괜찮습니다.

class Foo
  def self.define_getters(*symbols)
    symbols.each do |symbol|
      eval "def #{symbol}; @#{symbol}; end"
    end
  end

  define_getters :foo, :bar, :baz
end

그러나 적어도 Ruby 1.9.1에서 Ruby는 정말 강력한 메타 프로그래밍 방법을 가지고 있으며 다음을 수행 할 수 있습니다.

class Foo
  def self.define_getters(*symbols)
    symbols.each do |symbol|
      define_method(symbol) { instance_variable_get(symbol) }
    end
  end

  define_getters :foo, :bar, :baz
end

대부분의 목적을 위해이 방법을 사용하려면 탈출이 필요하지 않습니다.

다른 나쁜 점 eval 통역사가 문자열을 구문 분석하고 현재 바인딩 내부의 코드를 실행해야하므로 (적어도 루비에서) 상당히 느립니다. 다른 방법은 C 함수를 직접 호출하므로 속도 향상을 입어야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top