From 62300c6928699f22c8f4a1ca879b43d78d6a8bf6 Mon Sep 17 00:00:00 2001 From: Marius Wachtler Date: Fri, 22 Apr 2016 13:52:04 +0100 Subject: [PATCH 1/2] interpreter+bjit: fix leak when encountering a dict or set node with duplicate keys --- src/codegen/ast_interpreter.cpp | 13 +++++++++++-- src/codegen/baseline_jit.cpp | 13 ++++++++++--- test/tests/dict.py | 2 +- test/tests/set.py | 2 +- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/codegen/ast_interpreter.cpp b/src/codegen/ast_interpreter.cpp index 2e579cdc1..f66a91013 100644 --- a/src/codegen/ast_interpreter.cpp +++ b/src/codegen/ast_interpreter.cpp @@ -1574,8 +1574,13 @@ Value ASTInterpreter::visit_dict(AST_Dict* node) { BoxedDict* dict = new BoxedDict(); for (size_t i = 0; i < node->keys.size(); ++i) { Value v = visit_expr(node->values[i]); + AUTO_DECREF(v.o); Value k = visit_expr(node->keys[i]); - dict->d[k.o] = v.o; + AUTO_DECREF(k.o); + + int ret = PyDict_SetItem(dict, k.o, v.o); + if (ret == -1) + throwCAPIException(); values.push_back(v); keys.push_back(k); @@ -1590,7 +1595,11 @@ Value ASTInterpreter::visit_set(AST_Set* node) { BoxedSet::Set set; for (AST_expr* e : node->elts) { Value v = visit_expr(e); - set.insert(v.o); + auto&& p = set.insert(v.o); + if (!p.second /* already exists */) { + Py_DECREF(p.first->value); + *p.first = v.o; + } items.push_back(v); } diff --git a/src/codegen/baseline_jit.cpp b/src/codegen/baseline_jit.cpp index d7b34c8b4..befba6bc3 100644 --- a/src/codegen/baseline_jit.cpp +++ b/src/codegen/baseline_jit.cpp @@ -854,7 +854,9 @@ Box* JitFragmentWriter::callattrHelper(Box* obj, BoxedString* attr, CallattrFlag Box* JitFragmentWriter::createDictHelper(uint64_t num, Box** keys, Box** values) { BoxedDict* dict = (BoxedDict*)createDict(); for (uint64_t i = 0; i < num; ++i) { - dict->d[keys[i]] = values[i]; + int ret = PyDict_SetItem(dict, autoDecref(keys[i]), autoDecref(values[i])); + if (ret == -1) + throwCAPIException(); } return dict; } @@ -870,8 +872,13 @@ Box* JitFragmentWriter::createListHelper(uint64_t num, Box** data) { Box* JitFragmentWriter::createSetHelper(uint64_t num, Box** data) { BoxedSet* set = (BoxedSet*)createSet(); - for (int i = 0; i < num; ++i) - set->s.insert(data[i]); + for (int i = 0; i < num; ++i) { + auto&& p = set->s.insert(data[i]); + if (!p.second /* already exists */) { + Py_DECREF(p.first->value); + *p.first = data[i]; + } + } return set; } diff --git a/test/tests/dict.py b/test/tests/dict.py index bfcc40fd5..588f1ccd0 100644 --- a/test/tests/dict.py +++ b/test/tests/dict.py @@ -1,4 +1,4 @@ -d = {2:2} +d = {2:"should get overwritten", 2:2} d[1] = 1 print d print d[1], d[1L], d[1.0], d[True] diff --git a/test/tests/set.py b/test/tests/set.py index a48caf127..60430a764 100644 --- a/test/tests/set.py +++ b/test/tests/set.py @@ -1,4 +1,4 @@ -s1 = {1} +s1 = {1, 1} def sorted(s): l = list(s) From c6994906e2dfa7c0e0503fc9acedbbce0a2efd05 Mon Sep 17 00:00:00 2001 From: Marius Wachtler Date: Fri, 22 Apr 2016 11:42:40 +0100 Subject: [PATCH 2/2] fix a leak in interactive mode, -m mode and a leak when calling tp_setattr --- from_cpython/Modules/_io/bufferedio.c | 3 +++ src/jit.cpp | 4 +++- src/runtime/capi.cpp | 6 +++--- src/runtime/objmodel.cpp | 1 + 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/from_cpython/Modules/_io/bufferedio.c b/from_cpython/Modules/_io/bufferedio.c index 758edf420..d6cc6f798 100644 --- a/from_cpython/Modules/_io/bufferedio.c +++ b/from_cpython/Modules/_io/bufferedio.c @@ -732,6 +732,9 @@ _PyIO_trap_eintr(void) if (eintr_int == NULL) { eintr_int = PyLong_FromLong(EINTR); assert(eintr_int != NULL); + + // Pyston change: + PyGC_RegisterStaticConstant(eintr_int); } if (!PyErr_ExceptionMatches(PyExc_EnvironmentError)) return 0; diff --git a/src/jit.cpp b/src/jit.cpp index 5b06855c6..a18755fdf 100644 --- a/src/jit.cpp +++ b/src/jit.cpp @@ -476,7 +476,7 @@ static int main(int argc, char** argv) noexcept { } } else if (module != NULL) { // TODO: CPython uses the same main module for all code paths - main_module = createModule(boxString("__main__"), ""); + main_module = createModule(autoDecref(boxString("__main__")), ""); rtncode = (RunModule(module, 1) != 0); } else { main_module = createModule(autoDecref(boxString("__main__")), fn ? fn : ""); @@ -526,6 +526,8 @@ static int main(int argc, char** argv) noexcept { PyObject* v = PyImport_ImportModule("readline"); if (!v) PyErr_Clear(); + else + Py_CLEAR(v); printf("Pyston v%d.%d.%d (rev " STRINGIFY(GITREV) ")", PYSTON_VERSION_MAJOR, PYSTON_VERSION_MINOR, PYSTON_VERSION_MICRO); diff --git a/src/runtime/capi.cpp b/src/runtime/capi.cpp index 6b19ecef1..bdb323b6f 100644 --- a/src/runtime/capi.cpp +++ b/src/runtime/capi.cpp @@ -987,8 +987,6 @@ extern "C" int PyRun_InteractiveOneFlags(FILE* fp, const char* filename, PyCompi // Pyston change: // d = PyModule_GetDict(m); // v = run_mod(mod, filename, d, d, flags, arena); - v = None; - Py_INCREF(v); assert(PyModule_Check(m)); bool failed = false; try { @@ -1005,7 +1003,9 @@ extern "C" int PyRun_InteractiveOneFlags(FILE* fp, const char* filename, PyCompi PyErr_Print(); return -1; } - Py_DECREF(v); + // Pyston change: we dont't have v + // Py_DECREF(v); + if (Py_FlushLine()) PyErr_Clear(); return 0; diff --git a/src/runtime/objmodel.cpp b/src/runtime/objmodel.cpp index 88515456e..4acf8b0ab 100644 --- a/src/runtime/objmodel.cpp +++ b/src/runtime/objmodel.cpp @@ -3120,6 +3120,7 @@ extern "C" void setattr(Box* obj, BoxedString* attr, STOLEN(Box*) attr_val) { STAT_TIMER(t1, "us_timer_slowpath_tpsetattr", 10); assert(attr->data()[attr->size()] == '\0'); + AUTO_DECREF(attr_val); int rtn = obj->cls->tp_setattr(obj, const_cast(attr->data()), attr_val); if (rtn) throwCAPIException();