@@ -249,24 +249,56 @@ mod builtins {
249
249
#[ derive( FromArgs ) ]
250
250
struct ScopeArgs {
251
251
#[ pyarg( any, default ) ]
252
- globals : Option < PyDictRef > ,
252
+ globals : Option < PyObjectRef > ,
253
253
#[ pyarg( any, default ) ]
254
254
locals : Option < ArgMapping > ,
255
255
}
256
256
257
257
impl ScopeArgs {
258
- fn make_scope ( self , vm : & VirtualMachine ) -> PyResult < crate :: scope:: Scope > {
258
+ fn make_scope (
259
+ self ,
260
+ vm : & VirtualMachine ,
261
+ func_name : & ' static str ,
262
+ ) -> PyResult < crate :: scope:: Scope > {
263
+ fn validate_globals_dict (
264
+ globals : & PyObjectRef ,
265
+ vm : & VirtualMachine ,
266
+ func_name : & ' static str ,
267
+ ) -> PyResult < ( ) > {
268
+ if !globals. fast_isinstance ( vm. ctx . types . dict_type ) {
269
+ return Err ( match func_name {
270
+ "eval" => {
271
+ let is_mapping = crate :: protocol:: PyMapping :: check ( globals) ;
272
+ vm. new_type_error ( if is_mapping {
273
+ "globals must be a real dict; try eval(expr, {}, mapping)"
274
+ . to_owned ( )
275
+ } else {
276
+ "globals must be a dict" . to_owned ( )
277
+ } )
278
+ }
279
+ "exec" => vm. new_type_error ( format ! (
280
+ "exec() globals must be a dict, not {}" ,
281
+ globals. class( ) . name( )
282
+ ) ) ,
283
+ _ => vm. new_type_error ( "globals must be a dict" . to_owned ( ) ) ,
284
+ } ) ;
285
+ }
286
+ Ok ( ( ) )
287
+ }
288
+
259
289
let ( globals, locals) = match self . globals {
260
290
Some ( globals) => {
291
+ validate_globals_dict ( & globals, vm, func_name) ?;
292
+
293
+ let globals = PyDictRef :: try_from_object ( vm, globals) ?;
261
294
if !globals. contains_key ( identifier ! ( vm, __builtins__) , vm) {
262
295
let builtins_dict = vm. builtins . dict ( ) . into ( ) ;
263
296
globals. set_item ( identifier ! ( vm, __builtins__) , builtins_dict, vm) ?;
264
297
}
265
298
(
266
299
globals.clone ( ) ,
267
- self . locals . unwrap_or_else ( || {
268
- ArgMapping :: try_from_object ( vm, globals. into ( ) ) . unwrap ( )
269
- } ) ,
300
+ self . locals
301
+ . unwrap_or_else ( || ArgMapping :: from_dict_exact ( globals. clone ( ) ) ) ,
270
302
)
271
303
}
272
304
None => (
@@ -290,6 +322,8 @@ mod builtins {
290
322
scope : ScopeArgs ,
291
323
vm : & VirtualMachine ,
292
324
) -> PyResult {
325
+ let scope = scope. make_scope ( vm, "eval" ) ?;
326
+
293
327
// source as string
294
328
let code = match source {
295
329
Either :: A ( either) => {
@@ -323,18 +357,17 @@ mod builtins {
323
357
scope : ScopeArgs ,
324
358
vm : & VirtualMachine ,
325
359
) -> PyResult {
360
+ let scope = scope. make_scope ( vm, "exec" ) ?;
326
361
run_code ( vm, source, scope, crate :: compiler:: Mode :: Exec , "exec" )
327
362
}
328
363
329
364
fn run_code (
330
365
vm : & VirtualMachine ,
331
366
source : Either < PyStrRef , PyRef < crate :: builtins:: PyCode > > ,
332
- scope : ScopeArgs ,
367
+ scope : crate :: scope :: Scope ,
333
368
#[ allow( unused_variables) ] mode : crate :: compiler:: Mode ,
334
369
func : & str ,
335
370
) -> PyResult {
336
- let scope = scope. make_scope ( vm) ?;
337
-
338
371
// Determine code object:
339
372
let code_obj = match source {
340
373
#[ cfg( feature = "rustpython-compiler" ) ]
0 commit comments