forked from Mirrors/openclonk
Script: Prevent writes to constant arrays
parent
06b5f0e5ce
commit
99f704fbb8
|
@ -2262,9 +2262,9 @@ static bool FnCreateParticleAtBone(C4Object* Obj, C4String* szName, C4String* sz
|
|||
{
|
||||
if(Pos->GetSize() != 3)
|
||||
throw C4AulExecError("CreateParticleAtBone: Pos is not a three-vector");
|
||||
x.x = (*Pos)[0].getInt();
|
||||
x.y = (*Pos)[1].getInt();
|
||||
x.z = (*Pos)[2].getInt();
|
||||
x.x = (*Pos).GetItem(0).getInt();
|
||||
x.y = (*Pos).GetItem(1).getInt();
|
||||
x.z = (*Pos).GetItem(2).getInt();
|
||||
}
|
||||
else { x.x = x.y = x.z = 0.0f; }
|
||||
|
||||
|
@ -2272,9 +2272,9 @@ static bool FnCreateParticleAtBone(C4Object* Obj, C4String* szName, C4String* sz
|
|||
{
|
||||
if(Dir->GetSize() != 3)
|
||||
throw C4AulExecError("CreateParticleAtBone: Dir is not a three-vector");
|
||||
dir.x = (*Dir)[0].getInt() / 10.0f;
|
||||
dir.y = (*Dir)[1].getInt() / 10.0f;
|
||||
dir.z = (*Dir)[2].getInt() / 10.0f;
|
||||
dir.x = (*Dir).GetItem(0).getInt() / 10.0f;
|
||||
dir.y = (*Dir).GetItem(1).getInt() / 10.0f;
|
||||
dir.z = (*Dir).GetItem(2).getInt() / 10.0f;
|
||||
}
|
||||
else { dir.x = dir.y = dir.z = 0.0f; }
|
||||
// Apply the bone transformation to them, to go from bone coordinates
|
||||
|
|
|
@ -514,6 +514,8 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos)
|
|||
// Typcheck to determine whether it's an array or a proplist
|
||||
if(CheckArrayAccess(pStruct, pIndex) == C4V_Array)
|
||||
{
|
||||
if (pStruct->_getArray()->IsFrozen())
|
||||
throw C4AulExecError("array write: array is readonly");
|
||||
pStruct->_getArray()->SetItem(pIndex->_getInt(), *pValue);
|
||||
}
|
||||
else
|
||||
|
@ -566,6 +568,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos)
|
|||
throw C4AulExecError(FormatString("array slice: end index of type %s, int expected", EndIndex.GetTypeName()).getData());
|
||||
|
||||
C4ValueArray *pArray = Array._getArray();
|
||||
if (pArray->IsFrozen()) throw C4AulExecError("array write: array is readonly");
|
||||
pArray->SetSlice(StartIndex._getInt(), EndIndex._getInt(), Value);
|
||||
|
||||
// Set value as result, remove both indices and first copy of value
|
||||
|
|
|
@ -2655,6 +2655,8 @@ C4Value C4AulParse::Parse_ConstExpression(C4PropListStatic * parent, C4String *
|
|||
++size;
|
||||
}
|
||||
}
|
||||
if (Type == PARSER)
|
||||
r._getArray()->Freeze();
|
||||
Shift();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -837,6 +837,7 @@ static Nillable<C4String *> FnGetConstantNameByValue(C4PropList * _this, int val
|
|||
static bool FnSortArray(C4PropList * _this, C4ValueArray *pArray, bool descending)
|
||||
{
|
||||
if (!pArray) throw C4AulExecError("SortArray: no array given");
|
||||
if (pArray->IsFrozen()) throw C4AulExecError("array sort: array is readonly");
|
||||
// sort array by its members
|
||||
pArray->Sort(descending);
|
||||
return true;
|
||||
|
@ -846,6 +847,7 @@ static bool FnSortArrayByProperty(C4PropList * _this, C4ValueArray *pArray, C4St
|
|||
{
|
||||
if (!pArray) throw C4AulExecError("SortArrayByProperty: no array given");
|
||||
if (!prop_name) throw C4AulExecError("SortArrayByProperty: no property name given");
|
||||
if (pArray->IsFrozen()) throw C4AulExecError("array sort: array is readonly");
|
||||
// sort array by property
|
||||
if (!pArray->SortByProperty(prop_name, descending)) throw C4AulExecError("SortArrayByProperty: not all array elements are proplists");
|
||||
return true;
|
||||
|
@ -855,6 +857,7 @@ static bool FnSortArrayByArrayElement(C4PropList * _this, C4ValueArray *pArray,
|
|||
{
|
||||
if (!pArray) throw C4AulExecError("SortArrayByArrayElement: no array given");
|
||||
if (element_index<0) throw C4AulExecError("SortArrayByArrayElement: element index must be >=0");
|
||||
if (pArray->IsFrozen()) throw C4AulExecError("array sort: array is readonly");
|
||||
// sort array by array element
|
||||
if (!pArray->SortByArrayElement(element_index, descending)) throw C4AulExecError("SortArrayByArrayElement: not all array elements are arrays of sufficient length");
|
||||
return true;
|
||||
|
|
|
@ -22,18 +22,18 @@
|
|||
#include "object/C4Object.h"
|
||||
|
||||
C4ValueArray::C4ValueArray()
|
||||
: iSize(0), iCapacity(0), pData(NULL)
|
||||
: pData(NULL), iSize(0), iCapacity(0), constant(false)
|
||||
{
|
||||
}
|
||||
|
||||
C4ValueArray::C4ValueArray(int32_t inSize)
|
||||
: iSize(0), iCapacity(0), pData(NULL)
|
||||
: pData(NULL), iSize(0), iCapacity(0), constant(false)
|
||||
{
|
||||
SetSize(inSize);
|
||||
}
|
||||
|
||||
C4ValueArray::C4ValueArray(const C4ValueArray &ValueArray2)
|
||||
: iSize(0), iCapacity(0), pData(NULL)
|
||||
: pData(NULL), iSize(0), iCapacity(0), constant(false)
|
||||
{
|
||||
SetSize(ValueArray2.GetSize());
|
||||
for (int32_t i = 0; i < iSize; i++)
|
||||
|
@ -77,6 +77,7 @@ public:
|
|||
|
||||
void C4ValueArray::Sort(class C4SortObject &rSort)
|
||||
{
|
||||
assert(!constant);
|
||||
if (rSort.PrepareCache(this))
|
||||
{
|
||||
// Initialize position array
|
||||
|
@ -110,6 +111,7 @@ struct C4ValueArraySortStringscomp
|
|||
|
||||
void C4ValueArray::SortStrings()
|
||||
{
|
||||
assert(!constant);
|
||||
std::stable_sort(pData, pData+iSize, C4ValueArraySortStringscomp());
|
||||
}
|
||||
|
||||
|
@ -126,6 +128,7 @@ struct C4ValueArraySortcomp
|
|||
|
||||
void C4ValueArray::Sort(bool descending)
|
||||
{
|
||||
assert(!constant);
|
||||
// sort by whatever type the values have
|
||||
std::stable_sort(pData, pData+iSize, C4ValueArraySortcomp());
|
||||
if (descending) std::reverse(pData, pData+iSize);
|
||||
|
@ -146,6 +149,7 @@ struct C4ValueArraySortPropertycomp
|
|||
|
||||
bool C4ValueArray::SortByProperty(C4String *prop_name, bool descending)
|
||||
{
|
||||
assert(!constant);
|
||||
// expect this to be an array of proplists and sort by given property
|
||||
// make sure we're all proplists before
|
||||
for (int32_t i=0; i<iSize; ++i)
|
||||
|
@ -170,6 +174,7 @@ struct C4ValueArraySortArrayElementcomp
|
|||
bool C4ValueArray::SortByArrayElement(int32_t element_idx, bool descending)
|
||||
{
|
||||
assert(element_idx>=0);
|
||||
assert(!constant);
|
||||
// expect this to be an array of arrays and sort by given element
|
||||
// make sure we're all arrays before
|
||||
for (int32_t i=0; i<iSize; ++i)
|
||||
|
@ -189,6 +194,7 @@ C4Value &C4ValueArray::operator[](int32_t iElem)
|
|||
{
|
||||
assert(iElem < MaxSize);
|
||||
assert(iElem >= 0);
|
||||
assert(!constant);
|
||||
if (iElem >= iSize && iElem < MaxSize) this->SetSize(iElem + 1);
|
||||
// out-of-memory? This might not get caught, but it's better than a segfault
|
||||
assert(iElem < iSize);
|
||||
|
@ -198,6 +204,7 @@ C4Value &C4ValueArray::operator[](int32_t iElem)
|
|||
|
||||
void C4ValueArray::SetItem(int32_t iElem, const C4Value &Value)
|
||||
{
|
||||
assert(!constant);
|
||||
// enlarge
|
||||
if (iElem < -iSize)
|
||||
throw C4AulExecError("array access: index out of range");
|
||||
|
@ -214,6 +221,7 @@ void C4ValueArray::SetItem(int32_t iElem, const C4Value &Value)
|
|||
void C4ValueArray::SetSize(int32_t inSize)
|
||||
{
|
||||
if(inSize == iSize) return;
|
||||
assert(!constant);
|
||||
|
||||
// array not larger than allocated memory? Well, just ignore the additional allocated mem then
|
||||
if (inSize <= iCapacity)
|
||||
|
|
|
@ -57,6 +57,11 @@ public:
|
|||
void SetItem(int32_t iElemNr, const C4Value &Value); // interface for script
|
||||
void SetSize(int32_t inSize); // (enlarge only!)
|
||||
|
||||
// for arrays declared in script constants
|
||||
void Freeze() { constant = true; }
|
||||
void Thaw() { constant = false; }
|
||||
bool IsFrozen() const { return constant; }
|
||||
|
||||
void Denumerate(C4ValueNumbers *);
|
||||
|
||||
// comparison
|
||||
|
@ -77,8 +82,9 @@ public:
|
|||
bool SortByArrayElement(int32_t array_idx, bool descending=false); // checks that this is an array of all arrays and sorts by array elements at index. returns false if an element is not an array or smaller than array_idx+1
|
||||
|
||||
private:
|
||||
int32_t iSize, iCapacity;
|
||||
C4Value* pData;
|
||||
int32_t iSize, iCapacity;
|
||||
bool constant; // if true, this array is not changeable
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue