diff --git a/Python/generic_hash_mp.py b/Python/generic_hash_mp.py index 44003bdd3..53c00f6b4 100644 --- a/Python/generic_hash_mp.py +++ b/Python/generic_hash_mp.py @@ -37,7 +37,7 @@ def kernel_loop(ctx,passwords,salt_id,is_selftest): return hcmp.handle_queue(ctx,passwords,salt_id,is_selftest) def init(ctx): - hcmp.init(ctx,calc_hash,extract_esalts) + hcmp.init(ctx,extract_esalts) def term(ctx): hcmp.term(ctx) @@ -51,7 +51,8 @@ if __name__ == '__main__': "salts_buf": bytes(568), "esalts_buf": bytes(131080), "st_salts_buf": bytes(568), - "st_esalts_buf": bytes(131080) + "st_esalts_buf": bytes(131080), + "parallelism": 4 } init(ctx) hashcat_passwords = 256 @@ -62,5 +63,6 @@ if __name__ == '__main__': hashes = kernel_loop(ctx,passwords,0,False) passwords.clear() hashes = kernel_loop(ctx,passwords,0,False) ## remaining entries - if(len(hashes)): print(hashes[-1]) + if hashes: + print(hashes[-1]) term(ctx) diff --git a/Python/generic_hash_sp.py b/Python/generic_hash_sp.py index 76cc13f5b..d985b1693 100644 --- a/Python/generic_hash_sp.py +++ b/Python/generic_hash_sp.py @@ -37,7 +37,7 @@ def kernel_loop(ctx,passwords,salt_id,is_selftest): return hcsp.handle_queue(ctx,passwords,salt_id,is_selftest) def init(ctx): - hcsp.init(ctx,calc_hash,extract_esalts) + hcsp.init(ctx,extract_esalts) def term(ctx): hcsp.term(ctx) @@ -51,16 +51,19 @@ if __name__ == '__main__': "salts_buf": bytes(568), "esalts_buf": bytes(131080), "st_salts_buf": bytes(568), - "st_esalts_buf": bytes(131080) + "st_esalts_buf": bytes(131080), + "parallelism": 1 } init(ctx) hashcat_passwords = 256 passwords = [] for line in sys.stdin: passwords.append(bytes(line.rstrip(), 'utf-8')) - if(len(passwords) == hashcat_passwords): + if len(passwords) == hashcat_passwords: hashes = kernel_loop(ctx,passwords,0,False) passwords.clear() hashes = kernel_loop(ctx,passwords,0,False) ## remaining entries - if(len(hashes)): print(hashes[-1]) + if hashes: + print(hashes[-1]) term(ctx) + diff --git a/Python/hcmp.py b/Python/hcmp.py index 1e55ebfab..60af98b16 100644 --- a/Python/hcmp.py +++ b/Python/hcmp.py @@ -1,7 +1,13 @@ -import hcshared +import importlib import multiprocessing +import hcshared -def init(ctx: dict, user_fn, extract_esalts): +def _worker_batch(chunk, salt_id, is_selftest, module_name, salts, st_salts): + user_module = importlib.import_module(module_name) + calc_hash = getattr(user_module, "calc_hash") + return hcshared._worker_batch(chunk, salt_id, is_selftest, calc_hash, salts, st_salts) + +def init(ctx: dict, extract_esalts): # Extract and merge salts and esalts salts = hcshared.extract_salts(ctx["salts_buf"]) esalts = extract_esalts(ctx["esalts_buf"]) @@ -13,18 +19,19 @@ def init(ctx: dict, user_fn, extract_esalts): for salt, esalt in zip(st_salts, st_esalts): salt["esalt"] = esalt - # Save state in ctx + # Save in ctx ctx["salts"] = salts ctx["st_salts"] = st_salts - ctx["user_fn"] = user_fn + ctx["module_name"] = ctx.get("module_name", "__main__") + ctx["pool"] = multiprocessing.Pool(processes=ctx["parallelism"]) return def handle_queue(ctx: dict, passwords: list, salt_id: int, is_selftest: bool) -> list: - user_fn = ctx["user_fn"] + pool = ctx["pool"] salts = ctx["salts"] st_salts = ctx["st_salts"] - pool = ctx["pool"] + module_name = ctx["module_name"] parallelism = ctx["parallelism"] chunk_size = (len(passwords) + parallelism - 1) // parallelism @@ -34,8 +41,8 @@ def handle_queue(ctx: dict, passwords: list, salt_id: int, is_selftest: bool) -> for chunk in chunks: if chunk: jobs.append(pool.apply_async( - hcshared._worker_batch, - args=(chunk, salt_id, is_selftest, user_fn, salts, st_salts) + _worker_batch, + args=(chunk, salt_id, is_selftest, module_name, salts, st_salts) )) hashes = [] diff --git a/Python/hcsp.py b/Python/hcsp.py index 308529cfc..792674e74 100644 --- a/Python/hcsp.py +++ b/Python/hcsp.py @@ -1,12 +1,16 @@ +import importlib import hcshared def handle_queue(ctx: dict, passwords: list, salt_id: int, is_selftest: bool) -> list: - user_fn = ctx["user_fn"] + user_module = importlib.import_module(ctx["module_name"]) + calc_hash = getattr(user_module, "calc_hash") + salts = ctx["salts"] st_salts = ctx["st_salts"] - return hcshared._worker_batch (passwords, salt_id, is_selftest, user_fn, salts, st_salts) -def init(ctx: dict,user_fn,extract_esalts): + return hcshared._worker_batch(passwords, salt_id, is_selftest, calc_hash, salts, st_salts) + +def init(ctx: dict, extract_esalts): # Extract and merge salts and esalts salts = hcshared.extract_salts(ctx["salts_buf"]) esalts = extract_esalts(ctx["esalts_buf"]) @@ -18,10 +22,11 @@ def init(ctx: dict,user_fn,extract_esalts): for salt, esalt in zip(st_salts, st_esalts): salt["esalt"] = esalt - # Save state in ctx + # Store final state ctx["salts"] = salts ctx["st_salts"] = st_salts - ctx["user_fn"] = user_fn + ctx["module_name"] = ctx.get("module_name", "__main__") + return def term(ctx: dict): diff --git a/src/bridges/bridge_python_generic_hash_mp.c b/src/bridges/bridge_python_generic_hash_mp.c index a40d55373..f5d31aeab 100644 --- a/src/bridges/bridge_python_generic_hash_mp.c +++ b/src/bridges/bridge_python_generic_hash_mp.c @@ -72,6 +72,9 @@ typedef void (PYTHON_API_CALL *PYEXITSTATUSEXCEPTION) typedef PyStatus (PYTHON_API_CALL *PYINITIALIZEFROMCONFIG) (const PyConfig *); typedef void (PYTHON_API_CALL *PYEVAL_RESTORETHREAD) (PyThreadState *); typedef const char *(PYTHON_API_CALL *PYGETVERSION) (void); +typedef PyObject *(PYTHON_API_CALL *PY_COMPILESTRINGEXFLAGS) (const char *, const char *, int, PyCompilerFlags *, int); +typedef PyObject *(PYTHON_API_CALL *PYEVAL_EVALCODE) (PyObject *, PyObject *, PyObject *); +typedef PyObject *(PYTHON_API_CALL *PYEVAL_GETBUILTINS) (void); typedef struct hc_python_lib { @@ -125,6 +128,9 @@ typedef struct hc_python_lib PYINITIALIZEFROMCONFIG Py_InitializeFromConfig; PYEVAL_RESTORETHREAD PyEval_RestoreThread; PYGETVERSION Py_GetVersion; + PY_COMPILESTRINGEXFLAGS Py_CompileStringExFlags; + PYEVAL_EVALCODE PyEval_EvalCode; + PYEVAL_GETBUILTINS PyEval_GetBuiltins; } hc_python_lib_t; @@ -168,7 +174,7 @@ typedef struct PyObject *pArgs; PyObject *pContext; - PyObject *pModule; + PyObject *pGlobals; PyObject *pFunc_Init; PyObject *pFunc_Term; PyObject *pFunc_kernel_loop; @@ -189,11 +195,73 @@ typedef struct } python_interpreter_t; #if defined (_WIN) || defined (__CYGWIN__) || defined (__APPLE__) -static char *DEFAULT_SOURCE_FILENAME = "generic_hash_sp"; +static char *DEFAULT_SOURCE_FILENAME = "./Python/generic_hash_sp.py"; #else -static char *DEFAULT_SOURCE_FILENAME = "generic_hash_mp"; +static char *DEFAULT_SOURCE_FILENAME = "./Python/generic_hash_mp.py"; #endif +const char *extract_module_name (const char *path) +{ + char *filename = strdup (path); + + remove_file_suffix (filename, ".py"); + + const char *slash = strrchr (filename, '/'); + const char *backslash = strrchr (filename, '\\'); + + const char *module_name = NULL; + + if (slash) + { + module_name = slash + 1; + } + else if (backslash) + { + module_name = backslash + 1; + } + else + { + module_name = filename; + } + + return module_name; +} + +char *load_source (const char *filename) +{ + FILE *fp = fopen (filename, "r"); + + if (fp == NULL) + { + fprintf (stderr, "%s: %s\n", filename, strerror (errno)); + + return NULL; + } + + fseek (fp, 0, SEEK_END); + + const size_t size = ftell (fp); + + fseek (fp, 0, SEEK_SET); + + char *source = hcmalloc (size + 1); + + if (fread (source, 1, size, fp) != size) + { + fprintf (stderr, "%s: %s\n", filename, strerror (errno)); + + hcfree (source); + + return NULL; + } + + source[size] = 0; + + fclose (fp); + + return source; +} + #if defined (_WIN) #define DEVNULL "NUL" #else @@ -618,6 +686,9 @@ static bool init_python (hc_python_lib_t *python) //HC_LOAD_FUNC_PYTHON (python, Py_ExitStatusException, Py_ExitStatusException, PYEXITSTATUSEXCEPTION, PYTHON, 1); //HC_LOAD_FUNC_PYTHON (python, Py_InitializeFromConfig, Py_InitializeFromConfig, PYINITIALIZEFROMCONFIG, PYTHON, 1); HC_LOAD_FUNC_PYTHON (python, PyEval_RestoreThread, PyEval_RestoreThread, PYEVAL_RESTORETHREAD, PYTHON, 1); + HC_LOAD_FUNC_PYTHON (python, Py_CompileStringExFlags, Py_CompileStringExFlags, PY_COMPILESTRINGEXFLAGS, PYTHON, 1); + HC_LOAD_FUNC_PYTHON (python, PyEval_EvalCode, PyEval_EvalCode, PYEVAL_EVALCODE, PYTHON, 1); + HC_LOAD_FUNC_PYTHON (python, PyEval_GetBuiltins, PyEval_GetBuiltins, PYEVAL_GETBUILTINS, PYTHON, 1); return true; } @@ -720,29 +791,39 @@ void *platform_init (user_options_t *user_options) fprintf (stderr, " For multithreading on Windows and MacOS, please use -m 72000 instead.\n\n"); #endif - python_interpreter->source_filename = (user_options->bridge_parameter1) ? user_options->bridge_parameter1 : DEFAULT_SOURCE_FILENAME; + python_interpreter->source_filename = (user_options->bridge_parameter1 == NULL) ? DEFAULT_SOURCE_FILENAME : user_options->bridge_parameter1; - PyObject *pName = python->PyUnicode_DecodeFSDefault (python_interpreter->source_filename); + char *source = load_source (python_interpreter->source_filename); - if (pName == NULL) + if (source == NULL) return NULL; + + PyObject *code = python->Py_CompileStringExFlags (source, python_interpreter->source_filename, Py_file_input, NULL, -1); + + free (source); + + if (code == NULL) { python->PyErr_Print (); return false; } - unit_buf->pModule = python->PyImport_Import (pName); + unit_buf->pGlobals = python->PyDict_New (); - if (unit_buf->pModule == NULL) + python->PyDict_SetItemString (unit_buf->pGlobals, "__builtins__", python->PyEval_GetBuiltins ()); + + PyObject *result = python->PyEval_EvalCode (code, unit_buf->pGlobals, unit_buf->pGlobals); + + if (result == NULL) { python->PyErr_Print (); return false; } - python->Py_DecRef (pName); + python->Py_DecRef (result); - unit_buf->pFunc_Init = python->PyObject_GetAttrString (unit_buf->pModule, "init"); + unit_buf->pFunc_Init = python->PyDict_GetItemString (unit_buf->pGlobals, "init"); if (unit_buf->pFunc_Init == NULL) { @@ -751,7 +832,7 @@ void *platform_init (user_options_t *user_options) return false; } - unit_buf->pFunc_Term = python->PyObject_GetAttrString (unit_buf->pModule, "term"); + unit_buf->pFunc_Term = python->PyDict_GetItemString (unit_buf->pGlobals, "term"); if (unit_buf->pFunc_Term == NULL) { @@ -760,7 +841,7 @@ void *platform_init (user_options_t *user_options) return false; } - unit_buf->pFunc_kernel_loop = python->PyObject_GetAttrString (unit_buf->pModule, "kernel_loop"); + unit_buf->pFunc_kernel_loop = python->PyDict_GetItemString (unit_buf->pGlobals, "kernel_loop"); if (unit_buf->pFunc_kernel_loop == NULL) { @@ -815,7 +896,7 @@ void platform_term (void *platform_context) python->Py_DecRef (unit_buf->pFunc_kernel_loop); python->Py_DecRef (unit_buf->pFunc_Term); python->Py_DecRef (unit_buf->pFunc_Init); - python->Py_DecRef (unit_buf->pModule); + python->Py_DecRef (unit_buf->pGlobals); //python->PyEval_RestoreThread (python_interpreter->tstate); @@ -840,6 +921,9 @@ bool thread_init (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa int rc = 0; + const char *module_name = extract_module_name (python_interpreter->source_filename); + + rc |= python->PyDict_SetItemString (unit_buf->pContext, "module_name", python->PyUnicode_FromString ((const char *) module_name)); rc |= python->PyDict_SetItemString (unit_buf->pContext, "parallelism", python->PyLong_FromLong (unit_buf->parallelism)); rc |= python->PyDict_SetItemString (unit_buf->pContext, "salts_cnt", python->PyLong_FromLong (hashes->salts_cnt)); rc |= python->PyDict_SetItemString (unit_buf->pContext, "salts_size", python->PyLong_FromLong (sizeof (salt_t))); @@ -1052,7 +1136,7 @@ const char *st_update_hash (MAYBE_UNUSED void *platform_context) unit_buf->gstate = python->PyGILState_Ensure (); - PyObject *constant = python->PyObject_GetAttrString (unit_buf->pModule, "ST_HASH"); + PyObject *constant = python->PyDict_GetItemString (unit_buf->pGlobals, "ST_HASH"); if (constant == NULL) { @@ -1080,7 +1164,7 @@ const char *st_update_pass (MAYBE_UNUSED void *platform_context) unit_buf->gstate = python->PyGILState_Ensure (); - PyObject *constant = python->PyObject_GetAttrString (unit_buf->pModule, "ST_PASS"); + PyObject *constant = python->PyDict_GetItemString (unit_buf->pGlobals, "ST_PASS"); if (constant == NULL) { diff --git a/src/bridges/bridge_python_generic_hash_sp.c b/src/bridges/bridge_python_generic_hash_sp.c index beeb7d948..a53d4391a 100644 --- a/src/bridges/bridge_python_generic_hash_sp.c +++ b/src/bridges/bridge_python_generic_hash_sp.c @@ -72,6 +72,9 @@ typedef void (PYTHON_API_CALL *PYEXITSTATUSEXCEPTION) typedef PyStatus (PYTHON_API_CALL *PYINITIALIZEFROMCONFIG) (const PyConfig *); typedef void (PYTHON_API_CALL *PYEVAL_RESTORETHREAD) (PyThreadState *); typedef const char *(PYTHON_API_CALL *PYGETVERSION) (void); +typedef PyObject *(PYTHON_API_CALL *PY_COMPILESTRINGEXFLAGS) (const char *, const char *, int, PyCompilerFlags *, int); +typedef PyObject *(PYTHON_API_CALL *PYEVAL_EVALCODE) (PyObject *, PyObject *, PyObject *); +typedef PyObject *(PYTHON_API_CALL *PYEVAL_GETBUILTINS) (void); typedef struct hc_python_lib { @@ -125,6 +128,9 @@ typedef struct hc_python_lib PYINITIALIZEFROMCONFIG Py_InitializeFromConfig; PYEVAL_RESTORETHREAD PyEval_RestoreThread; PYGETVERSION Py_GetVersion; + PY_COMPILESTRINGEXFLAGS Py_CompileStringExFlags; + PYEVAL_EVALCODE PyEval_EvalCode; + PYEVAL_GETBUILTINS PyEval_GetBuiltins; } hc_python_lib_t; @@ -166,7 +172,7 @@ typedef struct PyObject *pArgs; PyObject *pContext; - PyObject *pModule; + PyObject *pGlobals; PyObject *pFunc_Init; PyObject *pFunc_Term; PyObject *pFunc_kernel_loop; @@ -186,7 +192,69 @@ typedef struct } python_interpreter_t; -static char *DEFAULT_SOURCE_FILENAME = "generic_hash_sp"; +static char *DEFAULT_SOURCE_FILENAME = "./Python/generic_hash_sp.py"; + +const char *extract_module_name (const char *path) +{ + char *filename = strdup (path); + + remove_file_suffix (filename, ".py"); + + const char *slash = strrchr (filename, '/'); + const char *backslash = strrchr (filename, '\\'); + + const char *module_name = NULL; + + if (slash) + { + module_name = slash + 1; + } + else if (backslash) + { + module_name = backslash + 1; + } + else + { + module_name = filename; + } + + return module_name; +} + +char *load_source (const char *filename) +{ + FILE *fp = fopen (filename, "r"); + + if (fp == NULL) + { + fprintf (stderr, "%s: %s\n", filename, strerror (errno)); + + return NULL; + } + + fseek (fp, 0, SEEK_END); + + const size_t size = ftell (fp); + + fseek (fp, 0, SEEK_SET); + + char *source = hcmalloc (size + 1); + + if (fread (source, 1, size, fp) != size) + { + fprintf (stderr, "%s: %s\n", filename, strerror (errno)); + + hcfree (source); + + return NULL; + } + + source[size] = 0; + + fclose (fp); + + return source; +} #if defined (_WIN) #define DEVNULL "NUL" @@ -628,6 +696,9 @@ static bool init_python (hc_python_lib_t *python) //HC_LOAD_FUNC_PYTHON (python, Py_ExitStatusException, Py_ExitStatusException, PYEXITSTATUSEXCEPTION, PYTHON, 1); //HC_LOAD_FUNC_PYTHON (python, Py_InitializeFromConfig, Py_InitializeFromConfig, PYINITIALIZEFROMCONFIG, PYTHON, 1); HC_LOAD_FUNC_PYTHON (python, PyEval_RestoreThread, PyEval_RestoreThread, PYEVAL_RESTORETHREAD, PYTHON, 1); + HC_LOAD_FUNC_PYTHON (python, Py_CompileStringExFlags, Py_CompileStringExFlags, PY_COMPILESTRINGEXFLAGS, PYTHON, 1); + HC_LOAD_FUNC_PYTHON (python, PyEval_EvalCode, PyEval_EvalCode, PYEVAL_EVALCODE, PYTHON, 1); + HC_LOAD_FUNC_PYTHON (python, PyEval_GetBuiltins, PyEval_GetBuiltins, PYEVAL_GETBUILTINS, PYTHON, 1); return true; } @@ -703,7 +774,7 @@ void *platform_init (user_options_t *user_options) python_interpreter->thread_state = python->PyEval_SaveThread (); - python_interpreter->source_filename = (user_options->bridge_parameter1) ? user_options->bridge_parameter1 : DEFAULT_SOURCE_FILENAME; + python_interpreter->source_filename = (user_options->bridge_parameter1 == NULL) ? DEFAULT_SOURCE_FILENAME : user_options->bridge_parameter1; if (units_init (python_interpreter) == false) { @@ -772,27 +843,37 @@ bool thread_init (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa python->Py_DecRef (path); python->Py_DecRef (sys); - PyObject *pName = python->PyUnicode_DecodeFSDefault (python_interpreter->source_filename); + char *source = load_source (python_interpreter->source_filename); - if (pName == NULL) + if (source == NULL) return NULL; + + PyObject *code = python->Py_CompileStringExFlags (source, python_interpreter->source_filename, Py_file_input, NULL, -1); + + free (source); + + if (code == NULL) { python->PyErr_Print (); return false; } - unit_buf->pModule = python->PyImport_Import (pName); + unit_buf->pGlobals = python->PyDict_New (); - if (unit_buf->pModule == NULL) + python->PyDict_SetItemString (unit_buf->pGlobals, "__builtins__", python->PyEval_GetBuiltins ()); + + PyObject *result = python->PyEval_EvalCode (code, unit_buf->pGlobals, unit_buf->pGlobals); + + if (result == NULL) { python->PyErr_Print (); return false; } - python->Py_DecRef (pName); + python->Py_DecRef (result); - unit_buf->pFunc_Init = python->PyObject_GetAttrString (unit_buf->pModule, "init"); + unit_buf->pFunc_Init = python->PyDict_GetItemString (unit_buf->pGlobals, "init"); if (unit_buf->pFunc_Init == NULL) { @@ -801,7 +882,7 @@ bool thread_init (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa return false; } - unit_buf->pFunc_Term = python->PyObject_GetAttrString (unit_buf->pModule, "term"); + unit_buf->pFunc_Term = python->PyDict_GetItemString (unit_buf->pGlobals, "term"); if (unit_buf->pFunc_Term == NULL) { @@ -810,7 +891,7 @@ bool thread_init (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa return false; } - unit_buf->pFunc_kernel_loop = python->PyObject_GetAttrString (unit_buf->pModule, "kernel_loop"); + unit_buf->pFunc_kernel_loop = python->PyDict_GetItemString (unit_buf->pGlobals, "kernel_loop"); if (unit_buf->pFunc_kernel_loop == NULL) { @@ -830,8 +911,13 @@ bool thread_init (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa return false; } + const char *module_name = extract_module_name (python_interpreter->source_filename); + int rc = 0; + + + rc |= python->PyDict_SetItemString (unit_buf->pContext, "module_name", python->PyUnicode_FromString ((const char *) module_name)); rc |= python->PyDict_SetItemString (unit_buf->pContext, "salts_cnt", python->PyLong_FromLong (hashes->salts_cnt)); rc |= python->PyDict_SetItemString (unit_buf->pContext, "salts_size", python->PyLong_FromLong (sizeof (salt_t))); rc |= python->PyDict_SetItemString (unit_buf->pContext, "salts_buf", python->PyBytes_FromStringAndSize ((const char *) hashes->salts_buf, sizeof (salt_t) * hashes->salts_cnt)); @@ -904,6 +990,7 @@ void thread_term (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa hc_python_lib_t *python = python_interpreter->python; + python->PyDict_DelItemString (unit_buf->pContext, "module_name"); python->PyDict_DelItemString (unit_buf->pContext, "salts_cnt"); python->PyDict_DelItemString (unit_buf->pContext, "salts_size"); python->PyDict_DelItemString (unit_buf->pContext, "salts_buf"); @@ -937,7 +1024,7 @@ void thread_term (MAYBE_UNUSED void *platform_context, MAYBE_UNUSED hc_device_pa python->Py_DecRef (unit_buf->pFunc_kernel_loop); python->Py_DecRef (unit_buf->pFunc_Term); python->Py_DecRef (unit_buf->pFunc_Init); - python->Py_DecRef (unit_buf->pModule); + python->Py_DecRef (unit_buf->pGlobals); python->Py_EndInterpreter (unit_buf->tstate); } @@ -1059,35 +1146,45 @@ const char *st_update_hash (MAYBE_UNUSED void *platform_context) python->PyEval_RestoreThread (python_interpreter->thread_state); + // this is ugly to load that entire thing just to get that one variable + PyObject *sys = python->PyImport_ImportModule ("sys"); PyObject *path = python->PyObject_GetAttrString (sys, "path"); python->PyList_Append (path, python->PyUnicode_FromString ("./Python")); python->Py_DecRef (path); python->Py_DecRef (sys); - PyObject *pName = python->PyUnicode_DecodeFSDefault (python_interpreter->source_filename); + char *source = load_source (python_interpreter->source_filename); - if (pName == NULL) + if (source == NULL) return NULL; + + PyObject *code = python->Py_CompileStringExFlags (source, python_interpreter->source_filename, Py_file_input, NULL, -1); + + free (source); + + if (code == NULL) { python->PyErr_Print (); - python_interpreter->thread_state = python->PyEval_SaveThread (); - return false; } - PyObject *pModule = python->PyImport_Import (pName); + PyObject *pGlobals = python->PyDict_New (); - if (pModule == NULL) + python->PyDict_SetItemString (pGlobals, "__builtins__", python->PyEval_GetBuiltins ()); + + PyObject *result = python->PyEval_EvalCode (code, pGlobals, pGlobals); + + if (result == NULL) { python->PyErr_Print (); - python_interpreter->thread_state = python->PyEval_SaveThread (); - return false; } - PyObject *constant = python->PyObject_GetAttrString (pModule, "ST_HASH"); + python->Py_DecRef (result); + + PyObject *constant = python->PyDict_GetItemString (pGlobals, "ST_HASH"); if (constant == NULL) { @@ -1119,29 +1216,39 @@ const char *st_update_pass (MAYBE_UNUSED void *platform_context) python->Py_DecRef (path); python->Py_DecRef (sys); - PyObject *pName = python->PyUnicode_DecodeFSDefault (python_interpreter->source_filename); + // this is ugly to load that entire thing just to get that one variable - if (pName == NULL) + char *source = load_source (python_interpreter->source_filename); + + if (source == NULL) return NULL; + + PyObject *code = python->Py_CompileStringExFlags (source, python_interpreter->source_filename, Py_file_input, NULL, -1); + + free (source); + + if (code == NULL) { python->PyErr_Print (); - python_interpreter->thread_state = python->PyEval_SaveThread (); - return false; } - PyObject *pModule = python->PyImport_Import (pName); + PyObject *pGlobals = python->PyDict_New (); - if (pModule == NULL) + python->PyDict_SetItemString (pGlobals, "__builtins__", python->PyEval_GetBuiltins ()); + + PyObject *result = python->PyEval_EvalCode (code, pGlobals, pGlobals); + + if (result == NULL) { python->PyErr_Print (); - python_interpreter->thread_state = python->PyEval_SaveThread (); - return false; } - PyObject *constant = python->PyObject_GetAttrString (pModule, "ST_PASS"); + python->Py_DecRef (result); + + PyObject *constant = python->PyDict_GetItemString (pGlobals, "ST_PASS"); if (constant == NULL) {