2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 14:37:41 +00:00

Compare commits

...

2 Commits

Author SHA1 Message Date
4cc56d561b Merge branch 'ticket/54' into working 2024-03-06 10:14:20 -07:00
96facaa7bb Make Python.Cheat command more usable by not parsing its argument
The argument is now always treated as a plain string and passed directly
to the cheat. This is the behavior expected by all the functions in
xCheat.py, which parse the string argument manually where needed.

The previous implementation evaluated the argument value as a Python
expression. This theoretically allowed passing non-string arguments, but
none of the cheats use this (and it's also a potential code execution
issue). If no argument was passed, the function was called with no
arguments, which is also not supported by any of the cheats.

In practice, this required unintuitive syntax for calling the cheats
correctly, for example:

    Python.Cheat GetPlayerID None
    Python.Cheat GetSDL "'FirstWeekClothing'"

With the new argument handling, these have been simplified to:

    Python.Cheat GetPlayerID
    Python.Cheat GetSDL FirstWeekClothing
2023-12-15 01:03:25 +01:00
3 changed files with 22 additions and 35 deletions

View File

@ -7061,17 +7061,12 @@ PF_CONSOLE_CMD( Python,
"string functions, ...", // Params
"Run a cheat command" )
{
std::string extraParms;
const char* extraParms = "";
if (numParams > 1)
{
extraParms = "(";
extraParms.append(params[1]);
extraParms.append(",)");
extraParms = params[1];
}
else
extraParms = "()";
PythonInterface::RunFunctionSafe("xCheat", params[0], extraParms.c_str());
PythonInterface::RunFunctionStringArg("xCheat", params[0], extraParms);
std::string output;
// get the messages

View File

@ -2102,38 +2102,32 @@ PyObject* PythonInterface::RunFunction(PyObject* module, const char* name, PyObj
return result;
}
PyObject* PythonInterface::ParseArgs(const char* args)
{
PyObject* result = NULL;
PyObject* scope = PyDict_New();
if (scope)
{
//- Py_eval_input makes this function accept only single expresion (not statement)
//- When using empty scope, functions and classes like 'file' or '__import__' are not visible
result = PyRun_String(args, Py_eval_input, scope, NULL);
Py_DECREF(scope);
}
return result;
}
bool PythonInterface::RunFunctionSafe(const char* module, const char* function, const char* args)
bool PythonInterface::RunFunctionStringArg(const char* module, const char* name, const char* arg)
{
PyObject* moduleObj = ImportModule(module);
bool result = false;
if (moduleObj)
{
PyObject* argsObj = ParseArgs(args);
if (argsObj)
PyObject* argObj = PyString_FromString(arg);
if (argObj)
{
PyObject* callResult = RunFunction(moduleObj, function, argsObj);
if (callResult)
PyObject* argsObj = PyTuple_New(1);
if (argsObj)
{
result = true;
Py_DECREF(callResult);
// PyTuple_SET_ITEM steals the reference to argObj.
PyTuple_SET_ITEM(argsObj, 0, argObj);
PyObject* callResult = RunFunction(moduleObj, name, argsObj);
if (callResult)
{
result = true;
Py_DECREF(callResult);
}
Py_DECREF(argsObj);
}
else
{
Py_DECREF(argObj);
}
Py_DECREF(argsObj);
}
Py_DECREF(moduleObj);
}

View File

@ -223,9 +223,7 @@ public:
static PyObject* RunFunction(PyObject* module, const char* name, PyObject* args);
static PyObject* ParseArgs(const char* args);
static bool RunFunctionSafe(const char* module, const char* function, const char* args);
static bool RunFunctionStringArg(const char* module, const char* name, const char* arg);
/////////////////////////////////////////////////////////////////////////////
//