From 1999726c180dacf699c93e4e5b9651977fc1c048 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 20 Nov 2022 22:09:56 +0800 Subject: [PATCH] fix pointer issues --- src/obj.h | 10 +++++++++- src/pocketpy.h | 13 +++++++++---- src/vm.h | 34 ++++++++++++++++++++++------------ 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/obj.h b/src/obj.h index c4e994fb..67dcd26a 100644 --- a/src/obj.h +++ b/src/obj.h @@ -14,13 +14,21 @@ const _Float _FLOAT_INF_NEG = -INFINITY; class CodeObject; class BasePointer; +class Pointer; class VM; +class Frame; class PkExportedResource {}; typedef std::shared_ptr _Pointer; typedef PyVar (*_CppFunc)(VM*, const pkpy::ArgList&); typedef std::shared_ptr _Code; +struct Pointer { + Frame* frame; // the frame that created this pointer + _Pointer ptr; // the internal pointer + Pointer(Frame* frame, _Pointer ptr) : frame(frame), ptr(ptr) {} +}; + struct Function { _Str name; _Code code; @@ -72,7 +80,7 @@ public: }; typedef std::shared_ptr _Func; -typedef std::variant<_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,_BoundedMethod,_Range,_Slice,_Pointer> _Value; +typedef std::variant<_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,_BoundedMethod,_Range,_Slice,_Pointer,Pointer> _Value; const int _SIZEOF_VALUE = sizeof(_Value); diff --git a/src/pocketpy.h b/src/pocketpy.h index bfa29e32..5b86c329 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -58,15 +58,19 @@ void __initializeBuiltinFunctions(VM* _vm) { _vm->bindMethod("pointer", "set", [](VM* vm, const pkpy::ArgList& args) { vm->__checkArgSize(args, 2, true); - _Pointer& p = std::get<_Pointer>(args[0]->_native); - p->set(vm, vm->topFrame(), args[1]); + Pointer& p = std::get(args[0]->_native); + // this check is unsafe, but it's the best we can do + if(!vm->__isFrameValid(p.frame)) vm->nullPointerError(); + p.ptr->set(vm, p.frame, args[1]); return vm->None; }); _vm->bindMethod("pointer", "get", [](VM* vm, const pkpy::ArgList& args) { vm->__checkArgSize(args, 1, true); - _Pointer& p = std::get<_Pointer>(args[0]->_native); - return p->get(vm, vm->topFrame()); + Pointer& p = std::get(args[0]->_native); + // this check is unsafe, but it's the best we can do + if(!vm->__isFrameValid(p.frame)) vm->nullPointerError(); + return p.ptr->get(vm, p.frame); }); _vm->bindBuiltinFunc("eval", [](VM* vm, const pkpy::ArgList& args) { @@ -131,6 +135,7 @@ void __initializeBuiltinFunctions(VM* _vm) { std::vector<_Str> names; for (auto& [k, _] : args[0]->attribs) names.push_back(k); for (auto& [k, _] : args[0]->_type->attribs) { + if (k.str().find("__") == 0) continue; if (std::find(names.begin(), names.end(), k) == names.end()) names.push_back(k); } PyVarList ret; diff --git a/src/vm.h b/src/vm.h index e1010a84..829cc60b 100644 --- a/src/vm.h +++ b/src/vm.h @@ -45,7 +45,7 @@ typedef void(*PrintFn)(const VM*, const char*); class VM: public PkExportedResource{ private: - std::stack< std::unique_ptr > callstack; + std::deque< std::unique_ptr > callstack; PyVarDict _modules; // 3rd modules PyVar __py2py_call_signal; @@ -209,9 +209,8 @@ private: } break; case OP_UNARY_REF: { - PyVar obj = frame->__pop(); - _Pointer p = PyPointer_AS_C(obj); - frame->push(newObject(_tp_user_pointer, p)); + _Pointer p = PyPointer_AS_C(frame->__pop()); + frame->push(newObject(_tp_user_pointer, Pointer(frame, p))); } break; case OP_POP_JUMP_IF_FALSE: if(!PyBool_AS_C(asBool(frame->popValue(this)))) frame->jump(byte.arg); @@ -365,9 +364,16 @@ public: return asRepr(obj); } + bool __isFrameValid(Frame* frame){ + for(const auto& f : callstack){ + if(f.get() == frame) return true; + } + return false; + } + Frame* topFrame(){ if(callstack.size() == 0) UNREACHABLE(); - return callstack.top().get(); + return callstack.back().get(); } PyVar asRepr(const PyVar& obj){ @@ -504,7 +510,7 @@ public: throw RuntimeError("RecursionError", "maximum recursion depth exceeded", _cleanErrorAndGetSnapshots()); } Frame* frame = new Frame(code.get(), _module, locals); - callstack.push(std::unique_ptr(frame)); + callstack.emplace_back(std::unique_ptr(frame)); return frame; } @@ -519,16 +525,16 @@ public: if(frame == frameBase){ // [ frameBase<- ] break; }else{ - callstack.pop(); - frame = callstack.top().get(); + callstack.pop_back(); + frame = callstack.back().get(); frame->push(ret); } }else{ - frame = callstack.top().get(); // [ frameBase, newFrame<- ] + frame = callstack.back().get(); // [ frameBase, newFrame<- ] } } - callstack.pop(); + callstack.pop_back(); return ret; } @@ -772,9 +778,9 @@ private: std::stack<_Str> snapshots; while (!callstack.empty()){ if(snapshots.size() < 8){ - snapshots.push(callstack.top()->errorSnapshot()); + snapshots.push(callstack.back()->errorSnapshot()); } - callstack.pop(); + callstack.pop_back(); } return snapshots; } @@ -788,6 +794,10 @@ public: _error("SystemError", msg); } + void nullPointerError(){ + _error("NullPointerError", "pointer is invalid"); + } + void zeroDivisionError(){ _error("ZeroDivisionError", "division by zero"); }