Squirrel: Change SQRefCounted allocator to avoid undefined behaviour
This commit is contained in:
10
src/3rdparty/squirrel/squirrel/sqapi.cpp
vendored
10
src/3rdparty/squirrel/squirrel/sqapi.cpp
vendored
@@ -57,13 +57,12 @@ HSQUIRRELVM sq_open(SQInteger initialstacksize)
|
||||
SQSharedState *ss;
|
||||
SQVM *v;
|
||||
sq_new(ss, SQSharedState);
|
||||
v = (SQVM *)SQ_MALLOC(sizeof(SQVM));
|
||||
new (v) SQVM(ss);
|
||||
v = new (SQAllocationTag{}) SQVM(ss);
|
||||
ss->_root_vm = v;
|
||||
if(v->Init(nullptr, initialstacksize)) {
|
||||
return v;
|
||||
} else {
|
||||
sq_delete(v, SQVM);
|
||||
sq_delete_refcounted(v, SQVM);
|
||||
return nullptr;
|
||||
}
|
||||
return v;
|
||||
@@ -75,14 +74,13 @@ HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize)
|
||||
SQVM *v;
|
||||
ss=_ss(friendvm);
|
||||
|
||||
v= (SQVM *)SQ_MALLOC(sizeof(SQVM));
|
||||
new (v) SQVM(ss);
|
||||
v = new (SQAllocationTag{}) SQVM(ss);
|
||||
|
||||
if(v->Init(friendvm, initialstacksize)) {
|
||||
friendvm->Push(v);
|
||||
return v;
|
||||
} else {
|
||||
sq_delete(v, SQVM);
|
||||
sq_delete_refcounted(v, SQVM);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
5
src/3rdparty/squirrel/squirrel/sqarray.h
vendored
5
src/3rdparty/squirrel/squirrel/sqarray.h
vendored
@@ -12,8 +12,7 @@ private:
|
||||
}
|
||||
public:
|
||||
static SQArray* Create(SQSharedState *ss,SQInteger nInitialSize){
|
||||
SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray));
|
||||
new (newarray) SQArray(ss,nInitialSize);
|
||||
SQArray *newarray = new (SQAllocationTag{}) SQArray(ss,nInitialSize);
|
||||
return newarray;
|
||||
}
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
@@ -84,7 +83,7 @@ public:
|
||||
}
|
||||
void FinalFree() override
|
||||
{
|
||||
sq_delete(this, SQArray);
|
||||
sq_delete_refcounted(this, SQArray);
|
||||
}
|
||||
SQObjectPtrVec _values;
|
||||
};
|
||||
|
6
src/3rdparty/squirrel/squirrel/sqclass.cpp
vendored
6
src/3rdparty/squirrel/squirrel/sqclass.cpp
vendored
@@ -147,9 +147,8 @@ void SQInstance::Init(SQSharedState *ss)
|
||||
ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
|
||||
}
|
||||
|
||||
SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)
|
||||
SQInstance::SQInstance(SQSharedState *ss, SQClass *c)
|
||||
{
|
||||
_memsize = memsize;
|
||||
_class = c;
|
||||
SQUnsignedInteger nvalues = _class->_defaultvalues.size();
|
||||
for(SQUnsignedInteger n = 0; n < nvalues; n++) {
|
||||
@@ -158,9 +157,8 @@ SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)
|
||||
Init(ss);
|
||||
}
|
||||
|
||||
SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)
|
||||
SQInstance::SQInstance(SQSharedState *ss, SQInstance *i)
|
||||
{
|
||||
_memsize = memsize;
|
||||
_class = i->_class;
|
||||
SQUnsignedInteger nvalues = _class->_defaultvalues.size();
|
||||
for(SQUnsignedInteger n = 0; n < nvalues; n++) {
|
||||
|
20
src/3rdparty/squirrel/squirrel/sqclass.h
vendored
20
src/3rdparty/squirrel/squirrel/sqclass.h
vendored
@@ -31,8 +31,7 @@ struct SQClass : public CHAINABLE_OBJ
|
||||
SQClass(SQSharedState *ss,SQClass *base);
|
||||
public:
|
||||
static SQClass* Create(SQSharedState *ss,SQClass *base) {
|
||||
SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass));
|
||||
new (newclass) SQClass(ss, base);
|
||||
SQClass *newclass = new (SQAllocationTag{}) SQClass(ss, base);
|
||||
return newclass;
|
||||
}
|
||||
~SQClass();
|
||||
@@ -55,7 +54,7 @@ public:
|
||||
void Lock() { _locked = true; if(_base) _base->Lock(); }
|
||||
void Release() {
|
||||
if (_hook) { _hook(_typetag,0);}
|
||||
sq_delete(this, SQClass);
|
||||
sq_delete_refcounted(this, SQClass);
|
||||
}
|
||||
void Finalize();
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
@@ -81,14 +80,13 @@ public:
|
||||
struct SQInstance : public SQDelegable
|
||||
{
|
||||
void Init(SQSharedState *ss);
|
||||
SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize);
|
||||
SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize);
|
||||
SQInstance(SQSharedState *ss, SQClass *c);
|
||||
SQInstance(SQSharedState *ss, SQInstance *c);
|
||||
public:
|
||||
static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {
|
||||
|
||||
SQInteger size = calcinstancesize(theclass);
|
||||
SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
|
||||
new (newinst) SQInstance(ss, theclass,size);
|
||||
SQInstance *newinst = new (SQSizedAllocationTag(size)) SQInstance(ss, theclass);
|
||||
if(theclass->_udsize) {
|
||||
newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize);
|
||||
}
|
||||
@@ -97,8 +95,7 @@ public:
|
||||
SQInstance *Clone(SQSharedState *ss)
|
||||
{
|
||||
SQInteger size = calcinstancesize(_class);
|
||||
SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
|
||||
new (newinst) SQInstance(ss, this,size);
|
||||
SQInstance *newinst = new (SQSizedAllocationTag(size)) SQInstance(ss, this);
|
||||
if(_class->_udsize) {
|
||||
newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize);
|
||||
}
|
||||
@@ -143,9 +140,7 @@ public:
|
||||
}
|
||||
void FinalFree() override
|
||||
{
|
||||
SQInteger size = _memsize;
|
||||
this->~SQInstance();
|
||||
SQ_FREE(this, size);
|
||||
sq_delete_refcounted(this, SQInstance);
|
||||
}
|
||||
void Finalize() override;
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
@@ -157,7 +152,6 @@ public:
|
||||
SQClass *_class;
|
||||
SQUserPointer _userpointer;
|
||||
SQRELEASEHOOK _hook;
|
||||
SQInteger _memsize;
|
||||
SQObjectPtr _values[1];
|
||||
};
|
||||
|
||||
|
15
src/3rdparty/squirrel/squirrel/sqclosure.h
vendored
15
src/3rdparty/squirrel/squirrel/sqclosure.h
vendored
@@ -10,12 +10,11 @@ private:
|
||||
SQClosure(SQSharedState *ss,SQFunctionProto *func){_function=func; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}
|
||||
public:
|
||||
static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){
|
||||
SQClosure *nc=(SQClosure*)SQ_MALLOC(sizeof(SQClosure));
|
||||
new (nc) SQClosure(ss,func);
|
||||
SQClosure *nc = new (SQAllocationTag{}) SQClosure(ss,func);
|
||||
return nc;
|
||||
}
|
||||
void Release(){
|
||||
sq_delete(this,SQClosure);
|
||||
sq_delete_refcounted(this,SQClosure);
|
||||
}
|
||||
SQClosure *Clone()
|
||||
{
|
||||
@@ -48,8 +47,7 @@ private:
|
||||
SQGenerator(SQSharedState *ss,SQClosure *closure){_closure=closure;_state=eRunning;_ci._generator=nullptr;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}
|
||||
public:
|
||||
static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){
|
||||
SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator));
|
||||
new (nc) SQGenerator(ss,closure);
|
||||
SQGenerator *nc = new (SQAllocationTag{}) SQGenerator(ss,closure);
|
||||
return nc;
|
||||
}
|
||||
~SQGenerator()
|
||||
@@ -61,7 +59,7 @@ public:
|
||||
_stack.resize(0);
|
||||
_closure=_null_;}
|
||||
void Release(){
|
||||
sq_delete(this,SQGenerator);
|
||||
sq_delete_refcounted(this,SQGenerator);
|
||||
}
|
||||
bool Yield(SQVM *v);
|
||||
bool Resume(SQVM *v,SQInteger target);
|
||||
@@ -84,8 +82,7 @@ private:
|
||||
public:
|
||||
static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func)
|
||||
{
|
||||
SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(sizeof(SQNativeClosure));
|
||||
new (nc) SQNativeClosure(ss,func);
|
||||
SQNativeClosure *nc = new (SQAllocationTag{}) SQNativeClosure(ss,func);
|
||||
return nc;
|
||||
}
|
||||
SQNativeClosure *Clone()
|
||||
@@ -103,7 +100,7 @@ public:
|
||||
REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
|
||||
}
|
||||
void Release(){
|
||||
sq_delete(this,SQNativeClosure);
|
||||
sq_delete_refcounted(this,SQNativeClosure);
|
||||
}
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue);
|
||||
|
8
src/3rdparty/squirrel/squirrel/sqfuncproto.h
vendored
8
src/3rdparty/squirrel/squirrel/sqfuncproto.h
vendored
@@ -97,10 +97,9 @@ public:
|
||||
SQInteger nfunctions,SQInteger noutervalues,
|
||||
SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams)
|
||||
{
|
||||
SQFunctionProto *f;
|
||||
//I compact the whole class and members in a single memory allocation
|
||||
f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams));
|
||||
new (f) SQFunctionProto(ninstructions, nliterals, nparameters, nfunctions, noutervalues, nlineinfos, nlocalvarinfos, ndefaultparams);
|
||||
size_t size = _FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);
|
||||
SQFunctionProto *f = new (SQSizedAllocationTag(size)) SQFunctionProto(ninstructions, nliterals, nparameters, nfunctions, noutervalues, nlineinfos, nlocalvarinfos, ndefaultparams);
|
||||
return f;
|
||||
}
|
||||
void Release(){
|
||||
@@ -110,9 +109,8 @@ public:
|
||||
_DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues);
|
||||
//_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers
|
||||
_DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos);
|
||||
SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams);
|
||||
this->~SQFunctionProto();
|
||||
sq_vm_free(this,size);
|
||||
SQFunctionProto::SQDeallocate(this);
|
||||
}
|
||||
const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);
|
||||
SQInteger GetLine(SQInstruction *curr);
|
||||
|
4
src/3rdparty/squirrel/squirrel/sqobject.cpp
vendored
4
src/3rdparty/squirrel/squirrel/sqobject.cpp
vendored
@@ -90,7 +90,7 @@ SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx)
|
||||
SQWeakRef *SQRefCounted::GetWeakRef(SQObjectType type)
|
||||
{
|
||||
if(!_weakref) {
|
||||
sq_new(_weakref,SQWeakRef);
|
||||
_weakref = new (SQAllocationTag{}) SQWeakRef();
|
||||
_weakref->_obj._type = type;
|
||||
_weakref->_obj._unVal.pRefCounted = this;
|
||||
}
|
||||
@@ -109,7 +109,7 @@ void SQWeakRef::Release() {
|
||||
if(ISREFCOUNTED(_obj._type)) {
|
||||
_obj._unVal.pRefCounted->_weakref = nullptr;
|
||||
}
|
||||
sq_delete(this,SQWeakRef);
|
||||
sq_delete_refcounted(this,SQWeakRef);
|
||||
}
|
||||
|
||||
bool SQDelegable::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) {
|
||||
|
45
src/3rdparty/squirrel/squirrel/sqobject.h
vendored
45
src/3rdparty/squirrel/squirrel/sqobject.h
vendored
@@ -54,6 +54,14 @@ enum SQMetaMethod{
|
||||
|
||||
#define MINPOWER2 4
|
||||
|
||||
struct SQAllocationTag{};
|
||||
|
||||
struct SQSizedAllocationTag {
|
||||
size_t alloc_size;
|
||||
|
||||
SQSizedAllocationTag(size_t alloc_size) : alloc_size(alloc_size) {}
|
||||
};
|
||||
|
||||
struct SQRefCounted
|
||||
{
|
||||
SQRefCounted() { _uiRef = 0; _weakref = nullptr; }
|
||||
@@ -63,23 +71,44 @@ struct SQRefCounted
|
||||
struct SQWeakRef *_weakref;
|
||||
virtual void Release()=0;
|
||||
|
||||
inline void *operator new(size_t size, SQRefCounted *place) = delete;
|
||||
inline void operator delete(void *ptr, SQRefCounted *place) = delete;
|
||||
|
||||
/* Placement new/delete to prevent memory leaks if constructor throws an exception. */
|
||||
inline void *operator new(size_t size, SQRefCounted *place)
|
||||
inline void *operator new(size_t size, SQAllocationTag tag)
|
||||
{
|
||||
place->size = size;
|
||||
return place;
|
||||
size += sizeof(size_t);
|
||||
size_t *ptr = (size_t *)SQ_MALLOC(size);
|
||||
*ptr = size;
|
||||
return ptr + 1;
|
||||
}
|
||||
|
||||
inline void operator delete(void *ptr, SQRefCounted *place)
|
||||
inline static void SQDeallocate(void *ptr)
|
||||
{
|
||||
SQ_FREE(ptr, place->size);
|
||||
size_t *base = static_cast<size_t *>(ptr) - 1;
|
||||
SQ_FREE(base, *base);
|
||||
}
|
||||
|
||||
inline void operator delete(void *ptr, SQAllocationTag tag)
|
||||
{
|
||||
SQDeallocate(ptr);
|
||||
}
|
||||
|
||||
inline void *operator new(size_t size, SQSizedAllocationTag sized_tag)
|
||||
{
|
||||
size_t alloc_size = sized_tag.alloc_size + sizeof(size_t);
|
||||
size_t *ptr = (size_t *)SQ_MALLOC(alloc_size);
|
||||
*ptr = alloc_size;
|
||||
return ptr + 1;
|
||||
}
|
||||
|
||||
inline void operator delete(void *ptr, SQSizedAllocationTag sized_tag)
|
||||
{
|
||||
SQDeallocate(ptr);
|
||||
}
|
||||
|
||||
/* Never used but required. */
|
||||
inline void operator delete(void *ptr) { NOT_REACHED(); }
|
||||
|
||||
private:
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct SQWeakRef : SQRefCounted
|
||||
|
7
src/3rdparty/squirrel/squirrel/sqstate.cpp
vendored
7
src/3rdparty/squirrel/squirrel/sqstate.cpp
vendored
@@ -564,8 +564,7 @@ SQString *SQStringTable::Add(const SQChar *news,SQInteger len)
|
||||
return s; //found
|
||||
}
|
||||
|
||||
SQString *t=(SQString *)SQ_MALLOC(len+sizeof(SQString));
|
||||
new (t) SQString(news, len);
|
||||
SQString *t = new (SQSizedAllocationTag(len + sizeof(SQString))) SQString(news, len);
|
||||
t->_next = _strings[h];
|
||||
_strings[h] = t;
|
||||
_slotused++;
|
||||
@@ -615,9 +614,7 @@ void SQStringTable::Remove(SQString *bs)
|
||||
else
|
||||
_strings[h] = s->_next;
|
||||
_slotused--;
|
||||
SQInteger slen = s->_len;
|
||||
s->~SQString();
|
||||
SQ_FREE(s,sizeof(SQString) + slen);
|
||||
sq_delete_refcounted(s, SQString);
|
||||
return;
|
||||
}
|
||||
prev = s;
|
||||
|
5
src/3rdparty/squirrel/squirrel/sqtable.h
vendored
5
src/3rdparty/squirrel/squirrel/sqtable.h
vendored
@@ -45,8 +45,7 @@ private:
|
||||
public:
|
||||
static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize)
|
||||
{
|
||||
SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable));
|
||||
new (newtable) SQTable(ss, nInitialSize);
|
||||
SQTable *newtable = new (SQAllocationTag{}) SQTable(ss, nInitialSize);
|
||||
newtable->_delegate = nullptr;
|
||||
return newtable;
|
||||
}
|
||||
@@ -87,7 +86,7 @@ public:
|
||||
}
|
||||
void FinalFree() override
|
||||
{
|
||||
sq_delete(this, SQTable);
|
||||
sq_delete_refcounted(this, SQTable);
|
||||
}
|
||||
|
||||
};
|
||||
|
7
src/3rdparty/squirrel/squirrel/squserdata.h
vendored
7
src/3rdparty/squirrel/squirrel/squserdata.h
vendored
@@ -13,8 +13,7 @@ struct SQUserData : SQDelegable
|
||||
}
|
||||
static SQUserData* Create(SQSharedState *ss, SQInteger size)
|
||||
{
|
||||
SQUserData* ud = (SQUserData*)SQ_MALLOC(sizeof(SQUserData)+(size-1));
|
||||
new (ud) SQUserData(ss, size);
|
||||
SQUserData *ud = new (SQSizedAllocationTag(sizeof(SQUserData)+(size-1))) SQUserData(ss, size);
|
||||
return ud;
|
||||
}
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
@@ -23,9 +22,7 @@ struct SQUserData : SQDelegable
|
||||
#endif
|
||||
void Release() {
|
||||
if (_hook) _hook(_val,_size);
|
||||
SQInteger tsize = _size - 1;
|
||||
this->~SQUserData();
|
||||
SQ_FREE(this, sizeof(SQUserData) + tsize);
|
||||
sq_delete_refcounted(this, SQUserData);
|
||||
}
|
||||
|
||||
SQInteger _size;
|
||||
|
7
src/3rdparty/squirrel/squirrel/squtils.h
vendored
7
src/3rdparty/squirrel/squirrel/squtils.h
vendored
@@ -2,14 +2,17 @@
|
||||
#ifndef _SQUTILS_H_
|
||||
#define _SQUTILS_H_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
void *sq_vm_malloc(SQUnsignedInteger size);
|
||||
void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size);
|
||||
void sq_vm_free(void *p,SQUnsignedInteger size);
|
||||
|
||||
#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;}
|
||||
#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));}
|
||||
#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));static_assert(!std::is_base_of<SQRefCounted,__type>());}
|
||||
#define sq_delete_refcounted(__ptr,__type) {__ptr->~__type();__ptr->SQDeallocate(__ptr);}
|
||||
#define SQ_MALLOC(__size) sq_vm_malloc((__size));
|
||||
#define SQ_FREE(__ptr,__size) sq_vm_free((__ptr),(__size));
|
||||
#define SQ_FREE(__ptr,__size) {sq_vm_free((__ptr),(__size));static_assert(!std::is_base_of<SQRefCounted,std::remove_pointer_t<decltype(__ptr)>>());}
|
||||
#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc((__ptr),(__oldsize),(__size));
|
||||
|
||||
//sqvector mini vector class, supports objects by value
|
||||
|
2
src/3rdparty/squirrel/squirrel/sqvm.h
vendored
2
src/3rdparty/squirrel/squirrel/sqvm.h
vendored
@@ -122,7 +122,7 @@ public:
|
||||
_callsstack = &_callstackdata[0];
|
||||
_alloccallsstacksize = newsize;
|
||||
}
|
||||
void Release(){ sq_delete(this,SQVM); } //does nothing
|
||||
void Release(){ sq_delete_refcounted(this,SQVM); } //does nothing
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//stack functions for the api
|
||||
void Remove(SQInteger n);
|
||||
|
Reference in New Issue
Block a user