this repo has no description
at trunk 473 lines 16 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "cpython-data.h" 3#include "cpython-func.h" 4 5#include "api-handle.h" 6#include "builtins-module.h" 7#include "compile-utils.h" 8#include "exception-builtins.h" 9#include "fileutils.h" 10#include "marshal.h" 11#include "module-builtins.h" 12#include "modules.h" 13#include "object-builtins.h" 14#include "os.h" 15#include "runtime.h" 16#include "sys-module.h" 17 18namespace py { 19 20PY_EXPORT PyObject* Py_CompileString(const char* str, const char* filename, 21 int start) { 22 DCHECK(str != nullptr, "str must not be null"); 23 DCHECK(filename != nullptr, "filename must not be null"); 24 PyObject* filename_obj = PyUnicode_DecodeFSDefault(filename); 25 if (filename_obj == nullptr) return nullptr; 26 27 PyArena* arena = PyArena_New(); 28 if (arena == nullptr) { 29 Py_DECREF(filename_obj); 30 return nullptr; 31 } 32 33 struct _mod* mod = 34 PyParser_ASTFromStringObject(str, filename_obj, start, nullptr, arena); 35 if (mod == nullptr) { 36 PyArena_Free(arena); 37 Py_DECREF(filename_obj); 38 return nullptr; 39 } 40 PyObject* result = reinterpret_cast<PyObject*>( 41 PyAST_CompileObject(mod, filename_obj, nullptr, -1, arena)); 42 PyArena_Free(arena); 43 Py_DECREF(filename_obj); 44 return result; 45} 46 47PY_EXPORT int PyRun_AnyFile(FILE* fp, const char* filename) { 48 return PyRun_AnyFileExFlags(fp, filename, /*closeit=*/0, /*flags=*/nullptr); 49} 50 51PY_EXPORT int PyRun_AnyFileEx(FILE* fp, const char* filename, int closeit) { 52 return PyRun_AnyFileExFlags(fp, filename, closeit, /*flags=*/nullptr); 53} 54 55PY_EXPORT int PyRun_AnyFileExFlags(FILE* fp, const char* filename, int closeit, 56 PyCompilerFlags* flags) { 57 if (filename == nullptr) { 58 filename = "???"; 59 } 60 if (Py_FdIsInteractive(fp, filename)) { 61 int err = PyRun_InteractiveLoopFlags(fp, filename, flags); 62 if (closeit) fclose(fp); 63 return err; 64 } 65 return PyRun_SimpleFileExFlags(fp, filename, closeit, flags); 66} 67 68PY_EXPORT int PyRun_AnyFileFlags(FILE* fp, const char* filename, 69 PyCompilerFlags* flags) { 70 return PyRun_AnyFileExFlags(fp, filename, /*closeit=*/0, flags); 71} 72 73static PyObject* runMod(struct _mod* mod, PyObject* filename, PyObject* globals, 74 PyObject* locals, PyCompilerFlags* flags, 75 PyArena* arena) { 76 PyCodeObject* code = PyAST_CompileObject(mod, filename, flags, -1, arena); 77 if (code == nullptr) return nullptr; 78 PyObject* v = 79 PyEval_EvalCode(reinterpret_cast<PyObject*>(code), globals, locals); 80 Py_DECREF(code); 81 return v; 82} 83 84static PyObject* runPycFile(FILE* fp, const char* filename, Module& module, 85 PyCompilerFlags* flags) { 86 Thread* thread = Thread::current(); 87 Runtime* runtime = thread->runtime(); 88 HandleScope scope(thread); 89 90 word file_len; 91 unique_c_ptr<byte> buffer(OS::readFile(fp, &file_len)); 92 if (buffer == nullptr) { 93 std::fprintf(stderr, "Could not read file '%s'\n", filename); 94 std::fclose(fp); 95 return nullptr; 96 } 97 98 Object code_obj(&scope, NoneType::object()); 99 Marshal::Reader reader(&scope, thread, View<byte>(buffer.get(), file_len)); 100 Str filename_str(&scope, runtime->newStrFromCStr(filename)); 101 if (reader.readPycHeader(filename_str).isErrorException()) { 102 return nullptr; 103 } 104 code_obj = reader.readObject(); 105 std::fclose(fp); 106 107 Code code(&scope, *code_obj); 108 RawObject result = executeModule(thread, code, module); 109 if (!result.isError() && flags) { 110 flags->cf_flags |= (code.flags() & PyCF_MASK); 111 } 112 return result.isError() ? nullptr : ApiHandle::newReference(runtime, result); 113} 114 115static PyObject* moduleProxy(PyObject* module_obj) { 116 Thread* thread = Thread::current(); 117 HandleScope scope(thread); 118 Module module(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(module_obj))); 119 return ApiHandle::borrowedReference(thread->runtime(), module.moduleProxy()); 120} 121 122// A PyRun_InteractiveOneObject() auxiliary function that does not print the 123// error on failure. 124static int PyRun_InteractiveOneObjectEx(FILE* fp, PyObject* filename, 125 PyCompilerFlags* flags) { 126 PyObject* mod_name = PyUnicode_InternFromString("__main__"); 127 if (mod_name == nullptr) { 128 return -1; 129 } 130 // TODO(T46532201): If fp == stdin, fetch encoding from sys.stdin if possible 131 const char* ps1 = ""; 132 const char* ps2 = ""; 133 PyObject* ps1_obj = PySys_GetObject("ps1"); 134 if (ps1_obj != nullptr) { 135 if ((ps1_obj = PyObject_Str(ps1_obj)) == nullptr) { 136 PyErr_Clear(); 137 } else if (PyUnicode_Check(ps1_obj)) { 138 if ((ps1 = PyUnicode_AsUTF8(ps1_obj)) == nullptr) { 139 PyErr_Clear(); 140 ps1 = ""; 141 } 142 } 143 Py_XDECREF(ps1_obj); 144 } 145 PyObject* ps2_obj = PySys_GetObject("ps2"); 146 if (ps2_obj != nullptr) { 147 if ((ps2_obj = PyObject_Str(ps2_obj)) == nullptr) { 148 PyErr_Clear(); 149 } else if (PyUnicode_Check(ps2_obj)) { 150 if ((ps2 = PyUnicode_AsUTF8(ps2_obj)) == nullptr) { 151 PyErr_Clear(); 152 ps2 = ""; 153 } 154 } 155 Py_XDECREF(ps2_obj); 156 } 157 PyArena* arena = PyArena_New(); 158 if (arena == nullptr) { 159 Py_DECREF(mod_name); 160 return -1; 161 } 162 char* enc = nullptr; 163 int errcode = 0; 164 struct _mod* mod = PyParser_ASTFromFileObject( 165 fp, filename, enc, Py_single_input, ps1, ps2, flags, &errcode, arena); 166 if (mod == nullptr) { 167 Py_DECREF(mod_name); 168 PyArena_Free(arena); 169 if (errcode == E_EOF) { 170 PyErr_Clear(); 171 return E_EOF; 172 } 173 return -1; 174 } 175 PyObject* module = PyImport_AddModuleObject(mod_name); 176 Py_DECREF(mod_name); 177 if (module == nullptr) { 178 PyArena_Free(arena); 179 return -1; 180 } 181 PyObject* module_proxy = moduleProxy(module); 182 PyObject* result = runMod(mod, filename, /*globals=*/module_proxy, 183 /*locals=*/module_proxy, flags, arena); 184 PyArena_Free(arena); 185 if (result == nullptr) { 186 return -1; 187 } 188 Py_DECREF(result); 189 flushStdFiles(); 190 return 0; 191} 192 193PY_EXPORT int PyRun_InteractiveLoop(FILE* fp, const char* filename) { 194 return PyRun_InteractiveLoopFlags(fp, filename, /*flags=*/nullptr); 195} 196 197PY_EXPORT int PyRun_InteractiveLoopFlags(FILE* fp, const char* filename, 198 PyCompilerFlags* flags) { 199 PyObject* filename_str = PyUnicode_DecodeFSDefault(filename); 200 if (filename_str == nullptr) { 201 PyErr_Print(); 202 return -1; 203 } 204 205 PyCompilerFlags local_flags = _PyCompilerFlags_INIT; 206 if (flags == nullptr) { 207 flags = &local_flags; 208 } 209 // TODO(T46358395): Set sys.ps{1,2} in sys module if they don't exist 210 int err = 0; 211 int ret; 212 int nomem_count = 0; 213 do { 214 ret = PyRun_InteractiveOneObjectEx(fp, filename_str, flags); 215 if (ret == -1 && PyErr_Occurred()) { 216 // Prevent an endless loop after multiple consecutive MemoryErrors while 217 // still allowing an interactive command to fail with a MemoryError. 218 if (PyErr_ExceptionMatches(PyExc_MemoryError)) { 219 if (++nomem_count > 16) { 220 PyErr_Clear(); 221 err = -1; 222 break; 223 } 224 } else { 225 nomem_count = 0; 226 } 227 PyErr_Print(); 228 flushStdFiles(); 229 } else { 230 nomem_count = 0; 231 } 232 } while (ret != E_EOF); 233 Py_DECREF(filename_str); 234 return err; 235} 236 237static void setMainLoader(Thread* thread, Module& module, const char* filename, 238 SymbolId loader_name) { 239 Runtime* runtime = thread->runtime(); 240 HandleScope scope(thread); 241 Str filename_str(&scope, runtime->newStrFromCStr(filename)); 242 Str dunder_main_str(&scope, runtime->symbols()->at(ID(__main__))); 243 RawObject loader_obj = 244 thread->invokeFunction2(ID(_frozen_importlib_external), loader_name, 245 dunder_main_str, filename_str); 246 DCHECK(!loader_obj.isError(), "Unable to call file loader"); 247 Object loader(&scope, loader_obj); 248 moduleAtPutById(thread, module, ID(__loader__), loader); 249} 250 251PY_EXPORT int PyRun_SimpleFile(FILE* fp, const char* filename) { 252 return PyRun_SimpleFileExFlags(fp, filename, /*closeit=*/0, 253 /*flags=*/nullptr); 254} 255 256PY_EXPORT int PyRun_SimpleFileEx(FILE* fp, const char* filename, int closeit) { 257 return PyRun_SimpleFileExFlags(fp, filename, closeit, /*flags=*/nullptr); 258} 259 260PY_EXPORT int PyRun_SimpleFileExFlags(FILE* fp, const char* filename, 261 int closeit, PyCompilerFlags* flags) { 262 Thread* thread = Thread::current(); 263 Runtime* runtime = thread->runtime(); 264 HandleScope scope(thread); 265 266 Object module_obj(&scope, runtime->findModuleById(ID(__main__))); 267 if (module_obj.isErrorNotFound()) { 268 Object name(&scope, runtime->symbols()->at(ID(__main__))); 269 module_obj = runtime->newModule(name); 270 Object modules(&scope, runtime->modules()); 271 objectSetItem(thread, modules, name, module_obj); 272 } 273 Module module(&scope, *module_obj); 274 275 RawObject dunder_file = moduleAtById(thread, module, ID(__file__)); 276 if (dunder_file.isErrorNotFound()) { 277 Str filename_str(&scope, runtime->newStrFromCStr(filename)); 278 Object cached_obj(&scope, NoneType::object()); 279 moduleAtPutById(thread, module, ID(__file__), filename_str); 280 moduleAtPutById(thread, module, ID(__cached__), cached_obj); 281 } 282 283 PyObject* result; 284 const char* extension = std::strrchr(filename, '.'); 285 if (extension != nullptr && std::strcmp(extension, ".pyc") == 0) { 286 // Try to run a pyc file 287 setMainLoader(thread, module, filename, ID(SourcelessFileLoader)); 288 result = runPycFile(fp, filename, module, flags); 289 } else { 290 // When running from stdin, leave __main__.__loader__ alone 291 if (std::strcmp(filename, "<stdin>") != 0) { 292 setMainLoader(thread, module, filename, ID(SourceFileLoader)); 293 } 294 PyObject* module_proxy = 295 ApiHandle::borrowedReference(runtime, module.moduleProxy()); 296 result = PyRun_FileExFlags(fp, filename, Py_file_input, module_proxy, 297 module_proxy, closeit, flags); 298 } 299 flushStdFiles(); 300 301 int returncode; 302 if (result == nullptr) { 303 PyErr_Print(); 304 returncode = -1; 305 } else { 306 Py_DECREF(result); 307 returncode = 0; 308 } 309 310 Str dunder_file_name(&scope, runtime->symbols()->at(ID(__file__))); 311 RawObject del_result = 312 moduleDeleteAttribute(thread, module, dunder_file_name); 313 if (del_result.isError()) { 314 PyErr_Clear(); 315 } 316 317 return returncode; 318} 319 320PY_EXPORT int PyRun_SimpleString(const char* str) { 321 return PyRun_SimpleStringFlags(str, nullptr); 322} 323 324PY_EXPORT int PyRun_SimpleStringFlags(const char* str, PyCompilerFlags* flags) { 325 PyObject* module = PyImport_AddModule("__main__"); 326 if (module == nullptr) return -1; 327 PyObject* module_proxy = PyModule_GetDict(module); 328 PyObject* result = 329 PyRun_StringFlags(str, Py_file_input, module_proxy, module_proxy, flags); 330 if (result == nullptr) { 331 PyErr_Print(); 332 return -1; 333 } 334 Py_DECREF(result); 335 return 0; 336} 337 338PY_EXPORT void PyErr_Display(PyObject* /* exc */, PyObject* value, 339 PyObject* tb) { 340 Thread* thread = Thread::current(); 341 HandleScope scope(thread); 342 343 DCHECK(value != nullptr, "value must be given"); 344 Object value_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(value))); 345 Object tb_obj(&scope, tb ? ApiHandle::asObject(ApiHandle::fromPyObject(tb)) 346 : NoneType::object()); 347 if (displayException(thread, value_obj, tb_obj).isError()) { 348 // Don't propagate any exceptions that happened during printing. This isn't 349 // great, but it's necessary to match CPython. 350 thread->clearPendingException(); 351 } 352} 353 354PY_EXPORT void PyErr_Print() { PyErr_PrintEx(1); } 355 356PY_EXPORT void PyErr_PrintEx(int set_sys_last_vars) { 357 Thread* thread = Thread::current(); 358 if (set_sys_last_vars) { 359 printPendingExceptionWithSysLastVars(thread); 360 } else { 361 printPendingException(thread); 362 } 363} 364 365PY_EXPORT int PyOS_CheckStack() { UNIMPLEMENTED("PyOS_CheckStack"); } 366 367PY_EXPORT PyObject* PyRun_File(FILE* fp, const char* filename, int start, 368 PyObject* globals, PyObject* locals) { 369 return PyRun_FileExFlags(fp, filename, start, globals, locals, 370 /*closeit=*/0, /*flags=*/nullptr); 371} 372 373PY_EXPORT PyObject* PyRun_FileEx(FILE* fp, const char* filename, int start, 374 PyObject* globals, PyObject* locals, 375 int closeit) { 376 return PyRun_FileExFlags(fp, filename, start, globals, locals, closeit, 377 /*flags=*/nullptr); 378} 379 380PY_EXPORT PyObject* PyRun_FileExFlags(FILE* fp, const char* filename_cstr, 381 int start, PyObject* globals, 382 PyObject* locals, int closeit, 383 PyCompilerFlags* flags) { 384 word file_len; 385 unique_c_ptr<byte> buffer(OS::readFile(fp, &file_len)); 386 if (closeit) std::fclose(fp); 387 388 Thread* thread = Thread::current(); 389 Runtime* runtime = thread->runtime(); 390 HandleScope scope(thread); 391 392 int iflags = flags != nullptr ? flags->cf_flags : 0; 393 // C-API uses this flag but it's an error for managed to pass it in 394 iflags &= ~PyCF_SOURCE_IS_UTF8; 395 396 View<byte> data(buffer.get(), file_len); 397 Object source(&scope, runtime->newBytesWithAll(data)); 398 Str filename(&scope, runtime->newStrFromCStr(filename_cstr)); 399 SymbolId mode_id; 400 if (start == Py_single_input) { 401 mode_id = ID(single); 402 } else if (start == Py_file_input) { 403 mode_id = ID(exec); 404 } else if (start == Py_eval_input) { 405 mode_id = ID(eval); 406 } else { 407 thread->raiseWithFmt( 408 LayoutId::kValueError, 409 "mode must be 'Py_single_input', 'Py_file_input' or 'Py_eval_input'"); 410 return nullptr; 411 } 412 RawObject code = 413 compile(thread, source, filename, mode_id, iflags, Py_OptimizeFlag); 414 if (code.isError()) { 415 return nullptr; 416 } 417 Code code_code(&scope, code); 418 Object globals_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(globals))); 419 Object module_obj(&scope, NoneType::object()); 420 if (globals_obj.isModuleProxy()) { 421 module_obj = ModuleProxy::cast(*globals_obj).module(); 422 } else if (runtime->isInstanceOfDict(*globals_obj)) { 423 UNIMPLEMENTED("User-defined globals is unsupported"); 424 } else { 425 thread->raiseBadInternalCall(); 426 return nullptr; 427 } 428 Object implicit_globals(&scope, NoneType::object()); 429 if (locals != nullptr && globals != locals) { 430 implicit_globals = ApiHandle::asObject(ApiHandle::fromPyObject(locals)); 431 if (!runtime->isMapping(thread, implicit_globals)) { 432 thread->raiseBadInternalCall(); 433 return nullptr; 434 } 435 } 436 Module module(&scope, *module_obj); 437 RawObject result = thread->exec(code_code, module, implicit_globals); 438 return result.isError() ? nullptr : ApiHandle::newReference(runtime, result); 439} 440 441PY_EXPORT PyObject* PyRun_FileFlags(FILE* fp, const char* filename, int start, 442 PyObject* globals, PyObject* locals, 443 PyCompilerFlags* flags) { 444 return PyRun_FileExFlags(fp, filename, start, globals, locals, 445 /*closeit=*/0, flags); 446} 447 448PY_EXPORT PyObject* PyRun_String(const char* str, int start, PyObject* globals, 449 PyObject* locals) { 450 return PyRun_StringFlags(str, start, globals, locals, /*flags=*/nullptr); 451} 452 453PY_EXPORT PyObject* PyRun_StringFlags(const char* str, int start, 454 PyObject* globals, PyObject* locals, 455 PyCompilerFlags* flags) { 456 Thread* thread = Thread::current(); 457 PyObject* filename = ApiHandle::borrowedReference( 458 thread->runtime(), Runtime::internStrFromCStr(thread, "<string>")); 459 460 PyArena* arena = PyArena_New(); 461 if (arena == nullptr) return nullptr; 462 463 struct _mod* mod = 464 PyParser_ASTFromStringObject(str, filename, start, flags, arena); 465 PyObject* ret = nullptr; 466 if (mod != nullptr) { 467 ret = runMod(mod, filename, globals, locals, flags, arena); 468 } 469 PyArena_Free(arena); 470 return ret; 471} 472 473} // namespace py