python's eval() vs. ast.literal_eval() 사용
어떤 코드에 문제가 있어서eval()
생각할 수 있는 해결책으로 떠올랐습니다.이제 나는 한 번도 사용할 필요가 없었다.eval()
하지만, 나는 그것이 야기할 수 있는 잠재적인 위험에 대한 많은 정보를 접했다.하지만, 저는 그것을 사용하는 것에 대해 매우 조심하고 있습니다.
사용자로부터 입력을 받고 있는 상황입니다.
datamap = input('Provide some data here: ')
어디에datamap
사전이어야 합니다.여기저기 찾아보니eval()
해결할 수 있을 거야데이터를 사용하기 전에 입력의 종류를 확인할 수 있을 것 같아서 보안상의 대책을 강구할 수 있을 것 같습니다.
datamap = eval(input('Provide some data here: ')
if not isinstance(datamap, dict):
return
나는 그 문서들을 읽었지만 이것이 안전한지 아닌지 아직 확실하지 않다.데이터가 입력되는 즉시 또는 입력된 후에 평가합니까?datamap
변수는 호출됩니까?
이요?ast
모듈.literal_eval()
안전한 유일한 방법인가?
datamap = eval(input('Provide some data here: '))
안전하지 않다고 판단하기 전에 실제로 코드를 평가한다는 의미입니다.함수가 호출되는 즉시 코드를 평가합니다.의 위험성도 참조해 주세요.
ast.literal_eval
입력이 유효한 Python 데이터형이 아닌 경우 예외를 발생시키므로 입력이 올바르지 않은 경우 코드가 실행되지 않습니다.
사용하다ast.literal_eval
필요할 때 언제든지.보통 리터럴 Python 문을 평가해서는 안 됩니다.
ast.literal_eval()
Python 구문 중 일부만 유효하다고 간주합니다.
제공된 문자열 또는 노드는 문자열, 바이트, 숫자, 튜플, 목록, 딕트, 세트, 부울란 및 Python 리터럴 구조로만 구성될 수 있습니다.
None
.
패스__import__('os').system('rm -rf /a-path-you-really-care-about')
안으로ast.literal_eval()
에러가 발생하지만 파일은 삭제됩니다.
사용자가 일반 사전을 입력할 수 있도록 하는 것처럼 보이므로ast.literal_eval()
원하는 대로 안전하게 할 수 있습니다.
eval: 이것은 매우 강력하지만 신뢰할 수 없는 입력에서 평가하는 문자열을 받아들이는 경우에도 매우 위험합니다.평가 대상 문자열이 "os.system('rm -rf /')"이라고 가정하면 컴퓨터상의 모든 파일이 삭제됩니다.
ast.literal_eval: 표현식 노드 또는 Python 리터럴 또는 컨테이너 디스플레이를 포함하는 문자열을 안전하게 평가합니다.제공된 문자열 또는 노드는 문자열, 바이트, 숫자, 튜플, 목록, 딕트, 세트, 부울란, 없음, 바이트 및 집합의 Python 리터럴 구조로만 구성될 수 있습니다.
문::
eval(expression, globals=None, locals=None)
import ast
ast.literal_eval(node_or_string)
예제:
# python 2.x - doesn't accept operators in string format
import ast
ast.literal_eval('[1, 2, 3]') # output: [1, 2, 3]
ast.literal_eval('1+1') # output: ValueError: malformed string
# python 3.0 -3.6
import ast
ast.literal_eval("1+1") # output : 2
ast.literal_eval("{'a': 2, 'b': 3, 3:'xyz'}") # output : {'a': 2, 'b': 3, 3:'xyz'}
# type dictionary
ast.literal_eval("",{}) # output : Syntax Error required only one parameter
ast.literal_eval("__import__('os').system('rm -rf /')") # output : error
eval("__import__('os').system('rm -rf /')")
# output : start deleting all the files on your computer.
# restricting using global and local variables
eval("__import__('os').system('rm -rf /')",{'__builtins__':{}},{})
# output : Error due to blocked imports by passing '__builtins__':{} in global
# But still eval is not safe. we can access and break the code as given below
s = """
(lambda fc=(
lambda n: [
c for c in
().__class__.__bases__[0].__subclasses__()
if c.__name__ == n
][0]
):
fc("function")(
fc("code")(
0,0,0,0,"KABOOM",(),(),(),"","",0,""
),{}
)()
)()
"""
eval(s, {'__builtins__':{}})
코드 기기 in in in in in in().__class__.__bases__[0]
단지 그 자체일 뿐이다.이제 모든 서브클래스를 인스턴스화했습니다.여기서 메인enter code here
여기서 n이라는 이름의 클래스를 찾는 것이 목적입니다.
는 할 가 있다.code
및 "" " " " "function
이치노은 '보다 낫다'와 방법입니다.CPython
오브젝트 서브클래스에 접속하여 시스템을 접속합니다.
python 3.7 ast.literal_eval()부터는 엄격해졌습니다.임의 숫자의 덧셈과 뺄셈은 더 이상 허용되지 않습니다.링크
Python은 평가에 열심입니다.eval(input(...))
3)가 (Python 3)에 eval
나중에 데이터를 어떻게 처리하든 상관없습니다.그러므로, 이것은 안전하지 않다. 특히 당신이eval
사용자 입력
ast.literal_eval
.
예를 들어, 프롬프트에 이것을 입력하는 것은 매우 나쁠 수 있습니다.
__import__('os').system('rm -rf /a-path-you-really-care-about')
최근의 Python3 에서는 단순한 문자열을 해석하는 것이 아니라 ast.parse() 메서드를 사용하여 AST를 작성하고 해석해야 합니다.
이것은 간단한 산술식을 안전하게 평가하기 위해 Python 3.6+에서 ast.parse()를 올바르게 사용하는 완전한 예입니다.
import ast, operator, math
import logging
logger = logging.getLogger(__file__)
def safe_eval(s):
def checkmath(x, *args):
if x not in [x for x in dir(math) if not "__" in x]:
raise SyntaxError(f"Unknown func {x}()")
fun = getattr(math, x)
return fun(*args)
binOps = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
ast.Mod: operator.mod,
ast.Pow: operator.pow,
ast.Call: checkmath,
ast.BinOp: ast.BinOp,
}
unOps = {
ast.USub: operator.neg,
ast.UAdd: operator.pos,
ast.UnaryOp: ast.UnaryOp,
}
ops = tuple(binOps) + tuple(unOps)
tree = ast.parse(s, mode='eval')
def _eval(node):
if isinstance(node, ast.Expression):
logger.debug("Expr")
return _eval(node.body)
elif isinstance(node, ast.Str):
logger.debug("Str")
return node.s
elif isinstance(node, ast.Num):
logger.debug("Num")
return node.value
elif isinstance(node, ast.Constant):
logger.info("Const")
return node.value
elif isinstance(node, ast.BinOp):
logger.debug("BinOp")
if isinstance(node.left, ops):
left = _eval(node.left)
else:
left = node.left.value
if isinstance(node.right, ops):
right = _eval(node.right)
else:
right = node.right.value
return binOps[type(node.op)](left, right)
elif isinstance(node, ast.UnaryOp):
logger.debug("UpOp")
if isinstance(node.operand, ops):
operand = _eval(node.operand)
else:
operand = node.operand.value
return unOps[type(node.op)](operand)
elif isinstance(node, ast.Call):
args = [_eval(x) for x in node.args]
r = checkmath(node.func.id, *args)
return r
else:
raise SyntaxError(f"Bad syntax, {type(node)}")
return _eval(tree)
if __name__ == "__main__":
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
logger.addHandler(ch)
assert safe_eval("1+1") == 2
assert safe_eval("1+-5") == -4
assert safe_eval("-1") == -1
assert safe_eval("-+1") == -1
assert safe_eval("(100*10)+6") == 1006
assert safe_eval("100*(10+6)") == 1600
assert safe_eval("2**4") == 2**4
assert safe_eval("sqrt(16)+1") == math.sqrt(16) + 1
assert safe_eval("1.2345 * 10") == 1.2345 * 10
print("Tests pass")
사전만 더 수 .json.loads
json dicts son 、 json dicts 、 json dicts 에 son 、 json dicts 。데이터만 할 수 , 는 "의 입니다.literal_eval
.
나는 에 갇혔다.ast.literal_eval()
디버거에서 했는데, 'J IDEA'가 돌아왔어요.None
디버거 출력에 표시됩니다.
하지만 나중에 그 출력을 변수에 할당하고 코드로 인쇄했을 때.그것은 잘 작동했다.공유 코드 예:
import ast
sample_string = '[{"id":"XYZ_GTTC_TYR", "name":"Suction"}]'
output_value = ast.literal_eval(sample_string)
print(output_value)
Python 버전 3.6입니다.
언급URL : https://stackoverflow.com/questions/15197673/using-pythons-eval-vs-ast-literal-eval
'programing' 카테고리의 다른 글
데이터 테이블에서 기본 슬롯 isOpen 수정 Vuetify 2.0 (0) | 2022.09.19 |
---|---|
파일 크기(바이트)를 사람이 읽을 수 있는 문자열로 변환 (0) | 2022.09.14 |
Drupal의 기본 비밀번호 암호화 방법은 무엇입니까? (0) | 2022.09.14 |
max()를 사용하여 그룹을 사용하여 SQL을 다른 테이블로 이행합니다. (0) | 2022.09.14 |
JSFiddle과 JS가 같은 PHP Sandbox가 있나요? (0) | 2022.09.14 |