Back to home page

Enduro/X

 
 

    


0001 /*

0002     see copyright notice in pscript.h

0003 */
0004 #include "pspcheader.h"
0005 #include "psvm.h"
0006 #include "pstable.h"
0007 #include "psclass.h"
0008 #include "psfuncproto.h"
0009 #include "psclosure.h"
0010 
0011 
0012 
0013 PSClass::PSClass(PSSharedState *ss,PSClass *base)
0014 {
0015     _base = base;
0016     _typetag = 0;
0017     _hook = NULL;
0018     _udsize = 0;
0019     _locked = false;
0020     _constructoridx = -1;
0021     if(_base) {
0022         _constructoridx = _base->_constructoridx;
0023         _udsize = _base->_udsize;
0024         _defaultvalues.copy(base->_defaultvalues);
0025         _methods.copy(base->_methods);
0026         _COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST);
0027         __ObjAddRef(_base);
0028     }
0029     _members = base?base->_members->Clone() : PSTable::Create(ss,0);
0030     __ObjAddRef(_members);
0031 
0032     INIT_CHAIN();
0033     ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
0034 }
0035 
0036 void PSClass::Finalize() {
0037     _attributes.Null();
0038     _NULL_PSOBJECT_VECTOR(_defaultvalues,_defaultvalues.size());
0039     _methods.resize(0);
0040     _NULL_PSOBJECT_VECTOR(_metamethods,MT_LAST);
0041     __ObjRelease(_members);
0042     if(_base) {
0043         __ObjRelease(_base);
0044     }
0045 }
0046 
0047 PSClass::~PSClass()
0048 {
0049     REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
0050     Finalize();
0051 }
0052 
0053 bool PSClass::NewSlot(PSSharedState *ss,const PSObjectPtr &key,const PSObjectPtr &val,bool bstatic)
0054 {
0055     PSObjectPtr temp;
0056     bool belongs_to_static_table = type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic;
0057     if(_locked && !belongs_to_static_table)
0058         return false; //the class already has an instance so cannot be modified

0059     if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value

0060     {
0061         _defaultvalues[_member_idx(temp)].val = val;
0062         return true;
0063     }
0064     /* Fixes CVE-2021-41556 */
0065     if (_members->CountUsed() >= MEMBER_MAX_COUNT) {
0066         return false;
0067     }
0068 
0069     if(belongs_to_static_table) {
0070         PSInteger mmidx;
0071         if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) &&
0072             (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
0073             _metamethods[mmidx] = val;
0074         }
0075         else {
0076             PSObjectPtr theval = val;
0077             if(_base && type(val) == OT_CLOSURE) {
0078                 theval = _closure(val)->Clone();
0079                 _closure(theval)->_base = _base;
0080                 __ObjAddRef(_base); //ref for the closure

0081             }
0082             if(type(temp) == OT_NULL) {
0083                 bool isconstructor;
0084                 PSVM::IsEqual(ss->_constructoridx, key, isconstructor);
0085                 if(isconstructor) {
0086                     _constructoridx = (PSInteger)_methods.size();
0087                 }
0088                 PSClassMember m;
0089                 m.val = theval;
0090                 _members->NewSlot(key,PSObjectPtr(_make_method_idx(_methods.size())));
0091                 _methods.push_back(m);
0092             }
0093             else {
0094                 _methods[_member_idx(temp)].val = theval;
0095             }
0096         }
0097         return true;
0098     }
0099     PSClassMember m;
0100     m.val = val;
0101     _members->NewSlot(key,PSObjectPtr(_make_field_idx(_defaultvalues.size())));
0102     _defaultvalues.push_back(m);
0103     return true;
0104 }
0105 
0106 PSInstance *PSClass::CreateInstance()
0107 {
0108     if(!_locked) Lock();
0109     return PSInstance::Create(_opt_ss(this),this);
0110 }
0111 
0112 PSInteger PSClass::Next(const PSObjectPtr &refpos, PSObjectPtr &outkey, PSObjectPtr &outval)
0113 {
0114     PSObjectPtr oval;
0115     PSInteger idx = _members->Next(false,refpos,outkey,oval);
0116     if(idx != -1) {
0117         if(_ismethod(oval)) {
0118             outval = _methods[_member_idx(oval)].val;
0119         }
0120         else {
0121             PSObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
0122             outval = _realval(o);
0123         }
0124     }
0125     return idx;
0126 }
0127 
0128 bool PSClass::SetAttributes(const PSObjectPtr &key,const PSObjectPtr &val)
0129 {
0130     PSObjectPtr idx;
0131     if(_members->Get(key,idx)) {
0132         if(_isfield(idx))
0133             _defaultvalues[_member_idx(idx)].attrs = val;
0134         else
0135             _methods[_member_idx(idx)].attrs = val;
0136         return true;
0137     }
0138     return false;
0139 }
0140 
0141 bool PSClass::GetAttributes(const PSObjectPtr &key,PSObjectPtr &outval)
0142 {
0143     PSObjectPtr idx;
0144     if(_members->Get(key,idx)) {
0145         outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
0146         return true;
0147     }
0148     return false;
0149 }
0150 
0151 ///////////////////////////////////////////////////////////////////////

0152 void PSInstance::Init(PSSharedState *ss)
0153 {
0154     _userpointer = NULL;
0155     _hook = NULL;
0156     __ObjAddRef(_class);
0157     _delegate = _class->_members;
0158     INIT_CHAIN();
0159     ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
0160 }
0161 
0162 PSInstance::PSInstance(PSSharedState *ss, PSClass *c, PSInteger memsize)
0163 {
0164     _memsize = memsize;
0165     _class = c;
0166     PSUnsignedInteger nvalues = _class->_defaultvalues.size();
0167     for(PSUnsignedInteger n = 0; n < nvalues; n++) {
0168         new (&_values[n]) PSObjectPtr(_class->_defaultvalues[n].val);
0169     }
0170     Init(ss);
0171 }
0172 
0173 PSInstance::PSInstance(PSSharedState *ss, PSInstance *i, PSInteger memsize)
0174 {
0175     _memsize = memsize;
0176     _class = i->_class;
0177     PSUnsignedInteger nvalues = _class->_defaultvalues.size();
0178     for(PSUnsignedInteger n = 0; n < nvalues; n++) {
0179         new (&_values[n]) PSObjectPtr(i->_values[n]);
0180     }
0181     Init(ss);
0182 }
0183 
0184 void PSInstance::Finalize()
0185 {
0186     PSUnsignedInteger nvalues = _class->_defaultvalues.size();
0187     __ObjRelease(_class);
0188     _NULL_PSOBJECT_VECTOR(_values,nvalues);
0189 }
0190 
0191 PSInstance::~PSInstance()
0192 {
0193     REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
0194     if(_class){ Finalize(); } //if _class is null it was already finalized by the GC

0195 }
0196 
0197 bool PSInstance::GetMetaMethod(PSVM PS_UNUSED_ARG(*v),PSMetaMethod mm,PSObjectPtr &res)
0198 {
0199     if(type(_class->_metamethods[mm]) != OT_NULL) {
0200         res = _class->_metamethods[mm];
0201         return true;
0202     }
0203     return false;
0204 }
0205 
0206 bool PSInstance::InstanceOf(PSClass *trg)
0207 {
0208     PSClass *parent = _class;
0209     while(parent != NULL) {
0210         if(parent == trg)
0211             return true;
0212         parent = parent->_base;
0213     }
0214     return false;
0215 }