Skip to content

Commit 05482e5

Browse files
committed
Make RunString safer and more standard.
1 parent a2d6024 commit 05482e5

File tree

1 file changed

+40
-19
lines changed

1 file changed

+40
-19
lines changed

src/runtime/pythonengine.cs

+40-19
Original file line numberDiff line numberDiff line change
@@ -411,33 +411,54 @@ public static PyObject ModuleFromString(string name, string code)
411411
/// executing the code string as a PyObject instance, or null if
412412
/// an exception was raised.
413413
/// </remarks>
414-
public static PyObject RunString(string code)
414+
public static PyObject RunString(
415+
string code, IntPtr? globals = null, IntPtr? locals = null
416+
)
415417
{
416-
IntPtr globals = Runtime.PyEval_GetGlobals();
417-
IntPtr locals = Runtime.PyDict_New();
418-
419-
IntPtr builtins = Runtime.PyEval_GetBuiltins();
420-
Runtime.PyDict_SetItemString(locals, "__builtins__", builtins);
418+
bool borrowedGlobals = true;
419+
if (globals == null)
420+
{
421+
globals = Runtime.PyEval_GetGlobals();
422+
if (globals == IntPtr.Zero)
423+
{
424+
globals = Runtime.PyDict_New();
425+
Runtime.PyDict_SetItemString(
426+
globals.Value, "__builtins__",
427+
Runtime.PyEval_GetBuiltins()
428+
);
429+
borrowedGlobals = false;
430+
}
431+
}
421432

422-
IntPtr flag = (IntPtr)257; /* Py_file_input */
423-
IntPtr result = Runtime.PyRun_String(code, flag, globals, locals);
424-
Runtime.XDecref(locals);
425-
if (result == IntPtr.Zero)
433+
bool borrowedLocals = true;
434+
if (locals == null)
426435
{
427-
return null;
436+
locals = Runtime.PyDict_New();
437+
borrowedLocals = false;
428438
}
429-
return new PyObject(result);
430-
}
431439

432-
public static PyObject RunString(string code, IntPtr globals, IntPtr locals)
433-
{
434440
IntPtr flag = (IntPtr)257; /* Py_file_input */
435-
IntPtr result = Runtime.PyRun_String(code, flag, globals, locals);
436-
if (result == IntPtr.Zero)
441+
442+
try
437443
{
438-
return null;
444+
IntPtr result = Runtime.PyRun_String(
445+
code, flag, globals.Value, locals.Value
446+
);
447+
448+
if (Runtime.PyErr_Occurred() != 0)
449+
{
450+
throw new PythonException();
451+
}
452+
453+
return new PyObject(result);
454+
}
455+
finally
456+
{
457+
if (!borrowedLocals)
458+
Runtime.XDecref(locals.Value);
459+
if (!borrowedGlobals)
460+
Runtime.XDecref(globals.Value);
439461
}
440-
return new PyObject(result);
441462
}
442463
}
443464

0 commit comments

Comments
 (0)