From 088ca737a67061c7e45f4595909c6da284303ead Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 27 Aug 2024 17:26:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20base=20=E5=A2=9E=E5=8A=A0code=E5=88=86?= =?UTF-8?q?=E6=9E=90=E5=B7=A5=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/utils/tools.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/apps/utils/tools.py b/apps/utils/tools.py index b2c7e2ec..4c6639e1 100755 --- a/apps/utils/tools.py +++ b/apps/utils/tools.py @@ -8,6 +8,47 @@ import base64 import requests from io import BytesIO from rest_framework.serializers import ValidationError +import ast + +class CodeAnalyzer(ast.NodeVisitor): + def __init__(self): + self.errors = [] + + def analyze(self, code): + try: + tree = ast.parse(code) + self.visit(tree) + except SyntaxError as e: + self.errors.append(f"Syntax error at line {e.lineno}: {e.msg}") + + def visit_Import(self, node): + self.errors.append(f"Forbidden import statement at line {node.lineno}") + self.generic_visit(node) + + def visit_ImportFrom(self, node): + self.errors.append(f"Forbidden import-from statement at line {node.lineno}") + self.generic_visit(node) + + def visit_Exec(self, node): + self.errors.append(f"Forbidden exec statement at line {node.lineno}") + self.generic_visit(node) + + def visit_Call(self, node): + # Detect forbidden function calls like eval, open, etc. + if isinstance(node.func, ast.Name): + if node.func.id in ['eval', 'exec', 'open', 'compile']: + self.errors.append(f"Forbidden function '{node.func.id}' used at line {node.lineno}") + self.generic_visit(node) + + def visit_With(self, node): + # Detect forbidden with-open blocks + for item in node.items: + context_expr = item.context_expr + # For Python versions >= 3.9, context_expr is replaced by context_exprs + if isinstance(context_expr, ast.Call) and isinstance(context_expr.func, ast.Name): + if context_expr.func.id == 'open': + self.errors.append(f"Forbidden 'open' statement within 'with' block at line {node.lineno}") + self.generic_visit(node) def is_close(num1, num2=0, tolerance=1e-9): """