6565 re .IGNORECASE ,
6666)
6767
68+ # Regex for validating variable names passed to Symbol().
69+ # Allows single-letter, Greek names, and conventional multi-letter math
70+ # variable names. Must start with a letter and contain only alphanumerics
71+ # and underscores, with a reasonable length cap.
72+ _SAFE_VARIABLE_RE = re .compile (r"^[A-Za-z][A-Za-z0-9_]{0,49}$" )
73+
74+
75+ def validate_variable_name (name : str ) -> None :
76+ """
77+ Validate a user-supplied variable name before it reaches Symbol().
78+
79+ Applies the same length cap, denylist, and character-set checks that
80+ safe_parse_expr applies to full expressions, keeping the hardened
81+ boundary consistent across all user-controlled string inputs.
82+
83+ Raises:
84+ ValueError: If the name is invalid or contains dangerous patterns.
85+ """
86+ if not isinstance (name , str ):
87+ raise ValueError ("Variable name must be a string" )
88+
89+ stripped = name .strip ()
90+ if not stripped :
91+ raise ValueError ("Variable name must not be empty" )
92+
93+ if not _SAFE_VARIABLE_RE .match (stripped ):
94+ raise ValueError (
95+ "Variable name must start with a letter, contain only "
96+ "alphanumerics/underscores, and be at most 50 characters"
97+ )
98+
99+ if _DANGEROUS_PATTERNS .search (stripped ):
100+ raise ValueError ("Variable name contains disallowed constructs" )
101+
68102
69103def _build_safe_local_dict (extra_symbols : Optional [Dict [str , Any ]] = None ) -> dict :
70104 """
71105 Build the allow-listed local namespace for parse_expr.
72106
73107 Only mathematical symbols, constants, functions, and the internal
74108 sympy types that parse_expr's transformations emit are included.
109+ Includes common Greek-letter and multi-letter symbolic variable names
110+ used in standard mathematical and scientific notation.
75111 """
76112 safe = {
77- # Common symbolic variables
113+ # Common single-letter symbolic variables
78114 "x" : Symbol ("x" ),
79115 "y" : Symbol ("y" ),
80116 "z" : Symbol ("z" ),
@@ -91,6 +127,40 @@ def _build_safe_local_dict(extra_symbols: Optional[Dict[str, Any]] = None) -> di
91127 "u" : Symbol ("u" ),
92128 "v" : Symbol ("v" ),
93129 "w" : Symbol ("w" ),
130+ # Greek-letter symbolic variables (common in verification workloads)
131+ "alpha" : Symbol ("alpha" ),
132+ "beta" : Symbol ("beta" ),
133+ "gamma" : Symbol ("gamma" ),
134+ "delta" : Symbol ("delta" ),
135+ "epsilon" : Symbol ("epsilon" ),
136+ "zeta" : Symbol ("zeta" ),
137+ "eta" : Symbol ("eta" ),
138+ "theta" : Symbol ("theta" ),
139+ "iota" : Symbol ("iota" ),
140+ "kappa" : Symbol ("kappa" ),
141+ "mu" : Symbol ("mu" ),
142+ "nu" : Symbol ("nu" ),
143+ "xi" : Symbol ("xi" ),
144+ "omicron" : Symbol ("omicron" ),
145+ "rho" : Symbol ("rho" ),
146+ "sigma" : Symbol ("sigma" ),
147+ "tau" : Symbol ("tau" ),
148+ "upsilon" : Symbol ("upsilon" ),
149+ "phi" : Symbol ("phi" ),
150+ "chi" : Symbol ("chi" ),
151+ "psi" : Symbol ("psi" ),
152+ "omega" : Symbol ("omega" ),
153+ # Capital Greek letters commonly used as symbols
154+ "Alpha" : Symbol ("Alpha" ),
155+ "Beta" : Symbol ("Beta" ),
156+ "Gamma" : Symbol ("Gamma" ),
157+ "Delta" : Symbol ("Delta" ),
158+ "Theta" : Symbol ("Theta" ),
159+ "Lambda" : Symbol ("Lambda" ),
160+ "Sigma" : Symbol ("Sigma" ),
161+ "Phi" : Symbol ("Phi" ),
162+ "Psi" : Symbol ("Psi" ),
163+ "Omega" : Symbol ("Omega" ),
94164 # Mathematical constants
95165 "pi" : pi ,
96166 "e" : E ,
@@ -141,7 +211,9 @@ def _build_safe_local_dict(extra_symbols: Optional[Dict[str, Any]] = None) -> di
141211 return safe
142212
143213
144- # Pre-built global dict that strips builtins
214+ # Pre-built global dict that strips builtins.
215+ # IMPORTANT: A shallow copy is made per invocation (see safe_parse_expr)
216+ # to prevent cross-call mutation by SymPy transformations.
145217_SAFE_GLOBAL_DICT : dict = {"__builtins__" : {}}
146218
147219
@@ -192,7 +264,7 @@ def safe_parse_expr(
192264 return parse_expr (
193265 stripped ,
194266 local_dict = local_dict ,
195- global_dict = _SAFE_GLOBAL_DICT ,
267+ global_dict = dict ( _SAFE_GLOBAL_DICT ) ,
196268 transformations = transformations ,
197269 )
198270 except Exception as exc :
0 commit comments