Merge branch 'Preview4_0' into feature-vfs-security

This commit is contained in:
Robert MacGregor 2022-06-13 08:05:26 -04:00
commit 161ffc62fe
3013 changed files with 348715 additions and 182470 deletions

View file

@ -399,7 +399,12 @@ U32 ConditionalExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type)
TypeReq ConditionalExprNode::getPreferredType()
{
return trueExpr->getPreferredType();
// We can't make it calculate a type based on subsequent expressions as the expression
// could be a string, or just numbers. To play it safe, stringify anything that deals with
// a conditional, and let the interpreter cast as needed to other types safely.
//
// See: Regression Test 7 in ScriptTest. It has a string result in the else portion of the ?: ternary.
return TypeReqString;
}
//------------------------------------------------------------

View file

@ -1620,17 +1620,17 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
++ip; // To skip the recurse flag if the object wasnt found
if (curObject)
{
SimGroup* group = dynamic_cast<SimGroup*>(curObject);
if (group)
SimSet* set = dynamic_cast<SimSet*>(curObject);
if (set)
{
StringTableEntry intName = StringTable->insert(stack[_STK].getString());
bool recurse = code[ip - 1];
SimObject* obj = group->findObjectByInternalName(intName, recurse);
SimObject* obj = set->findObjectByInternalName(intName, recurse);
stack[_STK].setInt(obj ? obj->getId() : 0);
}
else
{
Con::errorf(ConsoleLogEntry::Script, "%s: Attempt to use -> on non-group %s of class %s.", getFileLine(ip - 2), curObject->getName(), curObject->getClassName());
Con::errorf(ConsoleLogEntry::Script, "%s: Attempt to use -> on non-set %s of class %s.", getFileLine(ip - 2), curObject->getName(), curObject->getClassName());
stack[_STK].setInt(0);
}
}

View file

@ -46,29 +46,28 @@
extern StringStack STR;
extern ConsoleValueStack<4096> gCallStack;
Vector<ConsoleValue::ConversionBuffer> ConsoleValue::sConversionBuffer;
DataChunker ConsoleValue::sConversionAllocator;
void ConsoleValue::init()
{
sConversionBuffer.reserve(8192);
sConversionAllocator.setChunkSize(8092);
}
void ConsoleValue::resetConversionBuffer()
{
sConversionBuffer.resetAndTreatAsScratchBuffer();
sConversionAllocator.freeBlocks();
}
char* ConsoleValue::convertToBuffer() const
{
ConversionBuffer conversion;
char* buffer = static_cast<char*>(sConversionAllocator.alloc(32));
if (type == ConsoleValueType::cvFloat)
dSprintf(conversion.buffer, ConversionBufferStride, "%.9g", f);
dSprintf(buffer, 32, "%.9g", f);
else
dSprintf(conversion.buffer, ConversionBufferStride, "%lld", i);
dSprintf(buffer, 32, "%lld", i);
sConversionBuffer.push_back(std::move(conversion));
return sConversionBuffer.last().buffer;
return buffer;
}
const char* ConsoleValue::getConsoleData() const

View file

@ -146,17 +146,7 @@ class ConsoleValue
S32 type;
enum Constants
{
ConversionBufferStride = 32
};
struct ConversionBuffer
{
char buffer[ConversionBufferStride];
};
static Vector<ConversionBuffer> sConversionBuffer;
static DataChunker sConversionAllocator;
char* convertToBuffer() const;
@ -239,8 +229,10 @@ public:
return f;
if (type == ConsoleValueType::cvInteger)
return i;
if (isStringType())
return dAtof(s);
if (type == ConsoleValueType::cvSTEntry)
return s == StringTable->EmptyString() ? 0.0f : dAtof(s);
if (type == ConsoleValueType::cvString)
return dStrcmp(s, "") == 0 ? 0.0f : dAtof(s);
return dAtof(getConsoleData());
}
@ -250,8 +242,10 @@ public:
return i;
if (type == ConsoleValueType::cvFloat)
return f;
if (isStringType())
return dAtoi(s);
if (type == ConsoleValueType::cvSTEntry)
return s == StringTable->EmptyString() ? 0 : dAtoi(s);
if (type == ConsoleValueType::cvString)
return dStrcmp(s, "") == 0 ? 0 : dAtoi(s);
return dAtoi(getConsoleData());
}
@ -275,8 +269,10 @@ public:
return (bool)i;
if (type == ConsoleValueType::cvFloat)
return (bool)f;
if (isStringType())
return dAtob(s);
if (type == ConsoleValueType::cvSTEntry)
return s == StringTable->EmptyString() ? false : dAtob(s);
if (type == ConsoleValueType::cvString)
return dStrcmp(s, "") == 0 ? false : dAtob(s);
return dAtob(getConsoleData());
}

View file

@ -2859,3 +2859,21 @@ DefineEngineFunction(getTimestamp, const char*, (), ,
return returnBuffer;
}
#ifdef TORQUE_TOOLS
DefineEngineFunction(systemCommand, S32, (const char* commandLineAction, const char* callBackFunction), (""), "")
{
if (commandLineAction != "")
{
S32 result = system(commandLineAction);
if (callBackFunction != "" && callBackFunction[0])
{
if (Con::isFunction(callBackFunction))
Con::executef(callBackFunction, result);
}
}
return -1;
}
#endif

View file

@ -387,7 +387,17 @@ DefineEngineFunction(isFile, bool, ( const char* fileName ),,
"@ingroup FileSystem")
{
return Torque::FS::IsFile(fileName);
Torque::Path givenPath(fileName);
if (givenPath.getFileName().isEmpty() && givenPath.getExtension().isNotEmpty())
{
//specially named or hidden files, like .gitignore parse incorrectly due to having
//"no" filename, so we adjust that
givenPath.setFileName(String(".") + givenPath.getExtension());
givenPath.setExtension("");
}
return Torque::FS::IsFile(givenPath);
}
DefineEngineFunction(isScriptFile, bool, (const char* fileName), ,
@ -860,4 +870,20 @@ DefineEngineFunction( createPath, bool, ( const char* path ),,
return Torque::FS::CreatePath(path);
}
DefineEngineFunction(deleteDirectory, bool, (const char* path), ,
"@brief Delete a directory from the hard drive\n\n"
"@param path Name and path of the folder to delete\n"
"@note THERE IS NO RECOVERY FROM THIS. Deleted files are gone for good.\n"
"@return True if file was successfully deleted\n"
"@ingroup FileSystem")
{
static char fileName[1024];
static char sandboxFileName[1024];
Con::expandScriptFilename(fileName, sizeof(fileName), path);
Platform::makeFullPathName(fileName, sandboxFileName, sizeof(sandboxFileName));
return Platform::deleteDirectory(sandboxFileName);
}
#endif // TORQUE_TOOLS

View file

@ -68,6 +68,8 @@ namespace Sim
ImplementNamedSet(SFXAmbienceSet)
ImplementNamedSet(TerrainMaterialSet)
ImplementNamedSet(DataBlockSet);
ImplementNamedSet(ForestBrushSet);
ImplementNamedSet(ForestItemDataSet);
ImplementNamedGroup(ActionMapGroup)
ImplementNamedGroup(ClientGroup)
ImplementNamedGroup(GuiGroup)

View file

@ -107,6 +107,8 @@ namespace Sim
DeclareNamedSet(SFXAmbienceSet);
DeclareNamedSet(TerrainMaterialSet);
DeclareNamedSet(DataBlockSet);
DeclareNamedSet(ForestBrushSet);
DeclareNamedSet(ForestItemDataSet);
DeclareNamedGroup(ActionMapGroup)
DeclareNamedGroup(ClientGroup)
DeclareNamedGroup(GuiGroup)

View file

@ -565,6 +565,8 @@ void init()
InstantiateNamedSet(SFXAmbienceSet);
InstantiateNamedSet(TerrainMaterialSet);
InstantiateNamedSet(DataBlockSet);
InstantiateNamedSet(ForestBrushSet);
InstantiateNamedSet(ForestItemDataSet);
InstantiateNamedGroup(ActionMapGroup);
InstantiateNamedGroup(ClientGroup);
InstantiateNamedGroup(GuiGroup);

View file

@ -77,6 +77,7 @@ SimObject::SimObject()
mObjectName = NULL;
mOriginalName = NULL;
mInternalName = NULL;
mInheritFrom = NULL;
nextNameObject = nullptr;
nextManagerNameObject = nullptr;
nextIdObject = NULL;
@ -154,6 +155,9 @@ void SimObject::initPersistFields()
addProtectedField( "name", TypeName, Offset(mObjectName, SimObject), &setProtectedName, &defaultProtectedGetFn,
"Optional global name of this object." );
addProtectedField("inheritFrom", TypeString, Offset(mInheritFrom, SimObject), &setInheritFrom, &defaultProtectedGetFn,
"Optional Name of object to inherit from as a parent.");
endGroup( "Ungrouped" );
@ -300,6 +304,10 @@ bool SimObject::writeField(StringTableEntry fieldname, const char* value)
void SimObject::writeFields(Stream &stream, U32 tabStop)
{
// Write static fields.
// Create a default object of the same type
ConsoleObject* defaultConObject = ConsoleObject::create(getClassName());
SimObject* defaultObject = dynamic_cast<SimObject*>(defaultConObject);
const AbstractClassRep::FieldList &list = getFieldList();
@ -328,6 +336,11 @@ void SimObject::writeFields(Stream &stream, U32 tabStop)
if (!writeField(f->pFieldname, valCopy))
continue;
//If the field hasn't been changed from the default value, then don't bother writing it out
const char* defaultValueCheck = defaultObject->getDataField(f->pFieldname, array);
if (defaultValueCheck && defaultValueCheck[0] != '\0' && dStricmp(defaultValueCheck, valCopy) == 0)
continue;
val = valCopy;
U32 expandedBufferSize = ( nBufferSize * 2 ) + dStrlen(f->pFieldname) + 32;
@ -362,6 +375,9 @@ void SimObject::writeFields(Stream &stream, U32 tabStop)
if(mFieldDictionary && mCanSaveFieldDictionary)
mFieldDictionary->writeFields(this, stream, tabStop);
// Cleanup our created default object
delete defaultConObject;
}
//-----------------------------------------------------------------------------
@ -1133,7 +1149,7 @@ const char *SimObject::getPrefixedDataField(StringTableEntry fieldName, const ch
//-----------------------------------------------------------------------------
void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *array, const char *value)
void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *_array, const char *value)
{
// Sanity!
AssertFatal(fieldName != NULL, "Cannot set object field value with NULL field name.");
@ -1142,7 +1158,7 @@ void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *arr
// Set value without prefix if there's no value.
if (*value == 0)
{
setDataField(fieldName, NULL, value);
setDataField(fieldName, _array, value);
return;
}
@ -1156,7 +1172,7 @@ void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *arr
if (fieldPrefix == StringTable->EmptyString())
{
// No, so set the data field in the usual way.
setDataField(fieldName, NULL, value);
setDataField(fieldName, _array, value);
return;
}
@ -1167,23 +1183,23 @@ void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *arr
if (dStrnicmp(value, fieldPrefix, fieldPrefixLength) != 0)
{
// No, so set the data field in the usual way.
setDataField(fieldName, NULL, value);
setDataField(fieldName, _array, value);
return;
}
// Yes, so set the data excluding the prefix.
setDataField(fieldName, NULL, value + fieldPrefixLength);
setDataField(fieldName, _array, value + fieldPrefixLength);
}
//-----------------------------------------------------------------------------
const char *SimObject::getPrefixedDynamicDataField(StringTableEntry fieldName, const char *array, const S32 fieldType)
const char *SimObject::getPrefixedDynamicDataField(StringTableEntry fieldName, const char *_array, const S32 fieldType)
{
// Sanity!
AssertFatal(fieldName != NULL, "Cannot get field value with NULL field name.");
// Fetch field value.
const char* pFieldValue = getDataField(fieldName, array);
const char* pFieldValue = getDataField(fieldName, _array);
// Sanity.
AssertFatal(pFieldValue != NULL, "Field value cannot be NULL.");
@ -2235,10 +2251,10 @@ bool SimObject::setProtectedName(void *obj, const char *index, const char *data)
{
if (preventNameChanging)
return false;
SimObject *object = static_cast<SimObject*>(obj);
if ( object->isProperlyAdded() )
object->assignName( data );
SimObject* object = static_cast<SimObject*>(obj);
if (object->isProperlyAdded())
object->assignName(data);
// always return false because we assign the name here
return false;
@ -2246,6 +2262,31 @@ bool SimObject::setProtectedName(void *obj, const char *index, const char *data)
//-----------------------------------------------------------------------------
bool SimObject::setInheritFrom(void* obj, const char* index, const char* data)
{
SimObject* object = static_cast<SimObject*>(obj);
SimObject* parent;
if (Sim::findObject(data, parent))
{
object->setCopySource(parent);
object->assignFieldsFrom(parent);
// copy any substitution statements
SimDataBlock* parent_db = dynamic_cast<SimDataBlock*>(parent);
if (parent_db)
{
SimDataBlock* currentNewObject_db = dynamic_cast<SimDataBlock*>(object);
if (currentNewObject_db)
currentNewObject_db->copySubstitutionsFrom(parent_db);
}
}
return true;
}
//-----------------------------------------------------------------------------
void SimObject::inspectPreApply()
{
}

View file

@ -299,6 +299,8 @@ class SimObject: public ConsoleObject, public TamlCallbacks
SimObject* nextManagerNameObject;
SimObject* nextIdObject;
StringTableEntry mInheritFrom;
/// SimGroup we're contained in, if any.
SimGroup* mGroup;
@ -380,6 +382,9 @@ class SimObject: public ConsoleObject, public TamlCallbacks
// Object name protected set method
static bool setProtectedName(void *object, const char *index, const char *data);
// Sets object to inherit default values from
static bool setInheritFrom(void* object, const char* index, const char* data);
public:
inline void setProgenitorFile(const char* pFile) { mProgenitorFile = StringTable->insert(pFile); }
inline StringTableEntry getProgenitorFile(void) const { return mProgenitorFile; }

View file

@ -1079,6 +1079,22 @@ TEST(Script, MiscRegressions)
)");
ASSERT_EQ(regression6.getBool(), true);
ConsoleValue regression7 = RunScript(R"(
function Tween::vectorAdd(%v1, %v2)
{
%temp = "";
for (%i = 0; %i < getWordCount(%v1); %i++) {
%e = getWord(%v1, %i) + getWord(%v2, %i);
%temp = %i == 0 ? %e : %temp SPC %e;
}
return %temp;
}
return Tween::vectorAdd("1 2 3", "4 5 6");
)");
ASSERT_STREQ(regression7.getString(), "5 7 9");
}
#endif