@@ -805,6 +805,21 @@ def _run_step_decomposer(problem_type: str, problem: str) -> str:
805805# 4. 可视化工具实现
806806# ─────────────────────────────────────────
807807
808+ def _plot_eval_impl (expr_str : str , xmin : float , xmax : float ) -> tuple :
809+ """在子进程中解析并求值单条曲线——跟 calculator 走同一个安全沙箱/进程池/超时,
810+ 避免 plot_function 成为绕开 _check_expr_safe 的另一个攻击面。"""
811+ import numpy as np
812+ import sympy as sp
813+ x_sym = sp .Symbol ("x" )
814+ sym_expr = sp .sympify (expr_str .replace ("^" , "**" ))
815+ fn = sp .lambdify (x_sym , sym_expr , "numpy" )
816+ x_arr = np .linspace (xmin , xmax , 2000 )
817+ y_arr = np .array (fn (x_arr ), dtype = complex )
818+ y_arr = np .real (y_arr )
819+ y_arr [np .abs (y_arr ) > 1e5 ] = np .nan
820+ return x_arr .tolist (), y_arr .tolist (), sp .latex (sym_expr )
821+
822+
808823def _run_plot_function (expressions , xmin = - 10 , xmax = 10 , ymin = None , ymax = None ,
809824 title = "" , labels = None ) -> str :
810825 try :
@@ -839,22 +854,27 @@ def _run_plot_function(expressions, xmin=-10, xmax=10, ymin=None, ymax=None,
839854 # 多条曲线用实线/虚线/点划线区分,颜色只用深色系
840855 line_styles = ["-" , "--" , "-." , ":" ]
841856 colors = ["#1a1a1a" , "#2255aa" , "#cc2200" , "#228833" , "#aa44bb" ]
842- x_sym = sp .Symbol ("x" )
843- x_arr = np .linspace (float (xmin ), float (xmax ), 2000 )
857+ _xmin , _xmax = float (xmin ), float (xmax )
844858
845859 for i , expr_str in enumerate (expressions ):
860+ err = _check_expr_safe (expr_str )
861+ if err :
862+ ax .text (0.05 , 0.95 - i * 0.07 , f"表达式被拒绝: { expr_str } ({ err } )" ,
863+ transform = ax .transAxes , fontsize = 9 , color = "red" )
864+ continue
846865 try :
847- sym_expr = sp .sympify (expr_str .replace ("^" , "**" ))
848- fn = sp .lambdify (x_sym , sym_expr , "numpy" )
849- y_arr = np .array (fn (x_arr ), dtype = complex )
850- y_arr = np .real (y_arr )
851- y_arr [np .abs (y_arr ) > 1e5 ] = np .nan
866+ fut = _CALC_POOL .submit (_plot_eval_impl , expr_str , _xmin , _xmax )
867+ x_list , y_list , latex_expr = fut .result (timeout = _CALC_TIMEOUT )
868+ x_arr , y_arr = np .array (x_list ), np .array (y_list )
852869 lbl = (labels [i ] if labels and i < len (labels )
853- else f"$y = { sp . latex ( sym_expr ) } $" )
870+ else f"$y = { latex_expr } $" )
854871 ax .plot (x_arr , y_arr ,
855872 color = colors [i % len (colors )],
856873 linestyle = line_styles [i % len (line_styles )],
857874 lw = 1.8 , label = lbl )
875+ except _FutTimeout :
876+ ax .text (0.05 , 0.95 - i * 0.07 , f"计算超时: { expr_str } " ,
877+ transform = ax .transAxes , fontsize = 9 , color = "red" )
858878 except Exception as e :
859879 ax .text (0.05 , 0.95 - i * 0.07 , f"解析失败: { expr_str } " ,
860880 transform = ax .transAxes , fontsize = 9 , color = "red" )
0 commit comments