Browse Source

Merge branch 'development' of https://github.com/GarageGames/Torque3D into memberMess

# Conflicts:
#	Engine/source/console/consoleFunctions.cpp
Azaezel 7 năm trước cách đây
mục cha
commit
cbce2ee805
100 tập tin đã thay đổi với 894 bổ sung400 xóa
  1. 3 2
      Engine/source/T3D/components/component.cpp
  2. 48 0
      Engine/source/T3D/convexShape.cpp
  3. 1 0
      Engine/source/T3D/convexShape.h
  4. 1 1
      Engine/source/T3D/decal/decalManager.cpp
  5. 3 2
      Engine/source/T3D/fx/particle.cpp
  6. 3 2
      Engine/source/T3D/fx/particleEmitter.cpp
  7. 2 2
      Engine/source/T3D/item.cpp
  8. 13 0
      Engine/source/T3D/prefab.cpp
  9. 2 0
      Engine/source/T3D/prefab.h
  10. 1 1
      Engine/source/T3D/shapeImage.cpp
  11. 101 0
      Engine/source/T3D/tsStatic.cpp
  12. 3 0
      Engine/source/T3D/tsStatic.h
  13. 3 2
      Engine/source/afx/afxMagicMissile.cpp
  14. 3 3
      Engine/source/afx/arcaneFX.cpp
  15. 1 1
      Engine/source/afx/ce/afxAudioBank.cpp
  16. 9 6
      Engine/source/afx/ce/afxParticleEmitter.cpp
  17. 3 3
      Engine/source/afx/ea/afxEA_PhraseEffect.cpp
  18. 5 5
      Engine/source/afx/rpg/afxRPGMagicSpell.cpp
  19. 9 7
      Engine/source/afx/ui/afxSpellButton.cpp
  20. 3 2
      Engine/source/afx/xm/afxXM_PathConform.cpp
  21. 5 4
      Engine/source/app/badWordFilter.cpp
  22. 1 1
      Engine/source/app/banList.cpp
  23. 1 1
      Engine/source/app/mainLoop.cpp
  24. 5 5
      Engine/source/app/net/net.cpp
  25. 2 2
      Engine/source/app/net/netExamples.cpp
  26. 41 30
      Engine/source/app/net/serverQuery.cpp
  27. 3 2
      Engine/source/cinterface/cinterface.cpp
  28. 3 2
      Engine/source/console/CMDscan.cpp
  29. 6 5
      Engine/source/console/CMDscan.l
  30. 2 2
      Engine/source/console/SimXMLDocument.cpp
  31. 3 2
      Engine/source/console/astAlloc.cpp
  32. 22 26
      Engine/source/console/codeInterpreter.cpp
  33. 2 2
      Engine/source/console/compiledEval.cpp
  34. 2 2
      Engine/source/console/compiler.cpp
  35. 17 16
      Engine/source/console/console.cpp
  36. 1 1
      Engine/source/console/console.h
  37. 2 2
      Engine/source/console/consoleDoc.cpp
  38. 25 20
      Engine/source/console/consoleFunctions.cpp
  39. 14 14
      Engine/source/console/consoleInternal.cpp
  40. 8 8
      Engine/source/console/consoleObject.cpp
  41. 2 2
      Engine/source/console/consoleXMLExport.cpp
  42. 3 3
      Engine/source/console/fieldBrushObject.cpp
  43. 12 10
      Engine/source/console/fileSystemFunctions.cpp
  44. 5 5
      Engine/source/console/persistenceManager.cpp
  45. 5 5
      Engine/source/console/scriptFilename.cpp
  46. 2 2
      Engine/source/console/sim.cpp
  47. 2 2
      Engine/source/console/simDatablock.cpp
  48. 1 1
      Engine/source/console/simFieldDictionary.cpp
  49. 14 14
      Engine/source/console/simObject.cpp
  50. 3 2
      Engine/source/console/simObjectMemento.cpp
  51. 1 1
      Engine/source/console/stringStack.h
  52. 5 5
      Engine/source/console/telnetDebugger.cpp
  53. 1 1
      Engine/source/core/frameAllocator.h
  54. 2 2
      Engine/source/core/stream/bitStream.cpp
  55. 3 2
      Engine/source/core/stringTable.cpp
  56. 5 4
      Engine/source/core/strings/findMatch.cpp
  57. 64 2
      Engine/source/core/strings/stringFunctions.cpp
  58. 35 2
      Engine/source/core/strings/stringFunctions.h
  59. 3 3
      Engine/source/core/strings/stringUnit.cpp
  60. 3 3
      Engine/source/core/tokenizer.cpp
  61. 3 2
      Engine/source/core/util/zip/centralDir.cpp
  62. 2 2
      Engine/source/core/util/zip/test/zipTestWrite.cpp
  63. 2 2
      Engine/source/gfx/Null/gfxNullDevice.cpp
  64. 4 3
      Engine/source/gfx/gfxStructs.cpp
  65. 3 3
      Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp
  66. 2 2
      Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp
  67. 1 1
      Engine/source/gfx/screenshot.cpp
  68. 3 3
      Engine/source/gui/containers/guiFormCtrl.cpp
  69. 4 3
      Engine/source/gui/controls/guiAnimBitmapCtrl.cpp
  70. 159 39
      Engine/source/gui/controls/guiConsole.cpp
  71. 32 0
      Engine/source/gui/controls/guiConsole.h
  72. 1 1
      Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp
  73. 1 1
      Engine/source/gui/controls/guiFileTreeCtrl.cpp
  74. 1 1
      Engine/source/gui/controls/guiListBoxCtrl.cpp
  75. 5 4
      Engine/source/gui/controls/guiPopUpCtrl.cpp
  76. 11 10
      Engine/source/gui/controls/guiPopUpCtrlEx.cpp
  77. 1 1
      Engine/source/gui/controls/guiTabPageCtrl.cpp
  78. 4 4
      Engine/source/gui/controls/guiTreeViewCtrl.cpp
  79. 1 1
      Engine/source/gui/core/guiControl.cpp
  80. 3 3
      Engine/source/gui/editor/guiDebugger.cpp
  81. 2 2
      Engine/source/gui/editor/guiEditCtrl.cpp
  82. 3 3
      Engine/source/gui/editor/guiFilterCtrl.cpp
  83. 1 1
      Engine/source/gui/utility/messageVector.cpp
  84. 4 4
      Engine/source/gui/worldEditor/terrainEditor.cpp
  85. 25 2
      Engine/source/gui/worldEditor/worldEditor.cpp
  86. 23 16
      Engine/source/i18n/lang.cpp
  87. 10 0
      Engine/source/main/main.cpp
  88. 10 10
      Engine/source/materials/materialDefinition.cpp
  89. 3 3
      Engine/source/module/moduleDefinition.h
  90. 2 2
      Engine/source/module/moduleManager.cpp
  91. 1 1
      Engine/source/persistence/taml/fsTinyXml.cpp
  92. 2 2
      Engine/source/persistence/taml/taml.cpp
  93. 1 1
      Engine/source/persistence/taml/tamlCustom.cpp
  94. 2 2
      Engine/source/persistence/taml/tamlCustom.h
  95. 4 3
      Engine/source/persistence/taml/tamlWriteNode.h
  96. 1 1
      Engine/source/persistence/taml/xml/tamlXmlParser.cpp
  97. 1 1
      Engine/source/platform/input/leapMotion/leapMotionDevice.cpp
  98. 1 1
      Engine/source/platform/input/oculusVR/oculusVRDevice.cpp
  99. 1 1
      Engine/source/platform/input/openVR/openVRProvider.cpp
  100. 1 1
      Engine/source/platform/input/razerHydra/razerHydraDevice.cpp

+ 3 - 2
Engine/source/T3D/components/component.cpp

@@ -547,8 +547,9 @@ const char * Component::getDescriptionText(const char *desc)
    // [tom, 1/12/2007] If it isn't a file, just do it the easy way
    if (!Platform::isFile(desc))
    {
-      newDesc = new char[dStrlen(desc) + 1];
-      dStrcpy(newDesc, desc);
+      dsize_t newDescLen = dStrlen(desc) + 1;
+      newDesc = new char[newDescLen];
+      dStrcpy(newDesc, desc, newDescLen);
 
       return newDesc;
    }

+ 48 - 0
Engine/source/T3D/convexShape.cpp

@@ -695,6 +695,54 @@ bool ConvexShape::buildPolyList( PolyListContext context, AbstractPolyList *plis
    return true;
 }
 
+bool ConvexShape::buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &)
+{
+   if (mGeometry.points.empty())
+      return false;
+
+   //Get the collision mesh geometry
+   {
+      ColladaUtils::ExportData::colMesh* colMesh;
+      exportData->colMeshes.increment();
+      colMesh = &exportData->colMeshes.last();
+
+      colMesh->mesh.setTransform(&mObjToWorld, mObjScale);
+      colMesh->mesh.setObject(this);
+
+      //Just get the visible
+      buildPolyList(PLC_Export, &colMesh->mesh, getWorldBox(), getWorldSphere());
+
+      colMesh->colMeshName = String::ToString("ColMesh%d-1", exportData->colMeshes.size());
+   }
+
+   //Next, process the geometry and materials.
+   //Convex shapes only have the one 'level', so we'll just rely on the export post-process to back-fill
+   if (isServerObject() && getClientObject())
+   {
+      ConvexShape* clientShape = dynamic_cast<ConvexShape*>(getClientObject());
+
+      exportData->meshData.increment();
+
+      //Prep a meshData for this shape in particular
+      ColladaUtils::ExportData::meshLODData* meshData = &exportData->meshData.last();
+
+      //Fill out the info we'll need later to actually append our mesh data for the detail levels during the processing phase
+      meshData->shapeInst = nullptr;
+      meshData->originatingObject = this;
+      meshData->meshTransform = mObjToWorld;
+      meshData->scale = mObjScale;
+
+      meshData->meshDetailLevels.increment();
+
+      ColladaUtils::ExportData::detailLevel* curDetail = &meshData->meshDetailLevels.last();
+
+      //Make sure we denote the size this detail level has
+      curDetail->size = 512;
+   }
+
+   return true;
+}
+
 void ConvexShape::_export( OptimizedPolyList *plist, const Box3F &box, const SphereF &sphere )
 {
    BaseMatInstance *matInst = mMaterialInst;

+ 1 - 0
Engine/source/T3D/convexShape.h

@@ -172,6 +172,7 @@ public:
    virtual void prepRenderImage( SceneRenderState *state );
    virtual void buildConvex( const Box3F &box, Convex *convex );
    virtual bool buildPolyList( PolyListContext context, AbstractPolyList *polyList, const Box3F &box, const SphereF &sphere );
+   virtual bool buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &);
    virtual bool castRay( const Point3F &start, const Point3F &end, RayInfo *info );
    virtual bool collideBox( const Point3F &start, const Point3F &end, RayInfo *info );
 

+ 1 - 1
Engine/source/T3D/decal/decalManager.cpp

@@ -1495,7 +1495,7 @@ bool DecalManager::_createDataFile()
 
    // See if we know our current mission name
    char missionName[1024];
-   dStrcpy( missionName, Con::getVariable( "$Client::MissionFile" ) );
+   dStrcpy( missionName, Con::getVariable( "$Client::MissionFile" ), 1024 );
    char *dot = dStrstr((const char*)missionName, ".mis");
    if(dot)
       *dot = '\0';

+ 3 - 2
Engine/source/T3D/fx/particle.cpp

@@ -594,8 +594,9 @@ bool ParticleData::preload(bool server, String &errorStr)
 
         animTexFrames.clear();
 
-        char* tokCopy = new char[dStrlen(animTexFramesString) + 1];
-        dStrcpy(tokCopy, animTexFramesString);
+        dsize_t tokLen = dStrlen(animTexFramesString) + 1;
+        char* tokCopy = new char[tokLen];
+        dStrcpy(tokCopy, animTexFramesString, tokLen);
 
         char* currTok = dStrtok(tokCopy, " \t");
         while (currTok != NULL) 

+ 3 - 2
Engine/source/T3D/fx/particleEmitter.cpp

@@ -608,8 +608,9 @@ bool ParticleEmitterData::onAdd()
 
       // First we parse particleString into a list of particle name tokens 
       Vector<char*> dataBlocks(__FILE__, __LINE__);
-      char* tokCopy = new char[dStrlen(particleString) + 1];
-      dStrcpy(tokCopy, particleString);
+      dsize_t tokLen = dStrlen(particleString) + 1;
+      char* tokCopy = new char[tokLen];
+      dStrcpy(tokCopy, particleString, tokLen);
 
       char* currTok = dStrtok(tokCopy, " \t");
       while (currTok != NULL) 

+ 2 - 2
Engine/source/T3D/item.cpp

@@ -1254,7 +1254,7 @@ DefineEngineMethod( Item, getLastStickyPos, const char*, (),,
                object->mStickyCollisionPos.y,
                object->mStickyCollisionPos.z);
    else
-      dStrcpy(ret, "0 0 0");
+      dStrcpy(ret, "0 0 0", bufSize);
 
    return ret;
 }
@@ -1277,7 +1277,7 @@ DefineEngineMethod( Item, getLastStickyNormal, const char *, (),,
                object->mStickyCollisionNormal.y,
                object->mStickyCollisionNormal.z);
    else
-      dStrcpy(ret, "0 0 0");
+      dStrcpy(ret, "0 0 0", bufSize);
 
    return ret;
 }

+ 13 - 0
Engine/source/T3D/prefab.cpp

@@ -538,6 +538,19 @@ bool Prefab::buildPolyList(PolyListContext context, AbstractPolyList* polyList,
    return true;
 }
 
+bool Prefab::buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &sphere)
+{
+   Vector<SceneObject*> foundObjects;
+   mChildGroup->findObjectByType(foundObjects);
+
+   for (S32 i = 0; i < foundObjects.size(); i++)
+   {
+      foundObjects[i]->buildExportPolyList(exportData, box, sphere);
+   }
+
+   return true;
+}
+
 ExplodePrefabUndoAction::ExplodePrefabUndoAction( Prefab *prefab )
 : UndoAction( "Explode Prefab" )
 {

+ 2 - 0
Engine/source/T3D/prefab.h

@@ -98,6 +98,8 @@ public:
 
    bool buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F &box, const SphereF& sphere);
 
+   bool buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &);
+
 protected:
 
    void _closeFile( bool removeFileNotify );

+ 1 - 1
Engine/source/T3D/shapeImage.cpp

@@ -522,7 +522,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
             if (stateSequence[j] && stateSequence[j][0] && stateSequenceRandomFlash[j]) {
                char bufferVis[128];
                dStrncpy(bufferVis, stateSequence[j], 100);
-               dStrcat(bufferVis, "_vis");
+               dStrcat(bufferVis, "_vis", 128);
                s.sequenceVis[i] = shape[i]->findSequence(bufferVis);
             }
             if (s.sequenceVis[i] != -1)

+ 101 - 0
Engine/source/T3D/tsStatic.cpp

@@ -1073,6 +1073,97 @@ bool TSStatic::buildPolyList(PolyListContext context, AbstractPolyList* polyList
    return true;
 }
 
+bool TSStatic::buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &)
+{
+   if (!mShapeInstance)
+      return false;
+
+   if (mCollisionType == Bounds)
+   {
+      ColladaUtils::ExportData::colMesh* colMesh;
+      exportData->colMeshes.increment();
+      colMesh = &exportData->colMeshes.last();
+
+      colMesh->mesh.setTransform(&mObjToWorld, mObjScale);
+      colMesh->mesh.setObject(this);
+
+      colMesh->mesh.addBox(mObjBox);
+
+      colMesh->colMeshName = String::ToString("ColBox%d-1", exportData->colMeshes.size());
+   }
+   else if (mCollisionType == VisibleMesh)
+   {
+      ColladaUtils::ExportData::colMesh* colMesh;
+      exportData->colMeshes.increment();
+      colMesh = &exportData->colMeshes.last();
+
+      colMesh->mesh.setTransform(&mObjToWorld, mObjScale);
+      colMesh->mesh.setObject(this);
+
+      mShapeInstance->buildPolyList(&colMesh->mesh, 0);
+
+      colMesh->colMeshName = String::ToString("ColMesh%d-1", exportData->colMeshes.size());
+   }
+   else if (mCollisionType == CollisionMesh)
+   {
+      // Everything else is done from the collision meshes
+      // which may be built from either the visual mesh or
+      // special collision geometry.
+      for (U32 i = 0; i < mCollisionDetails.size(); i++)
+      {
+         ColladaUtils::ExportData::colMesh* colMesh;
+         exportData->colMeshes.increment();
+         colMesh = &exportData->colMeshes.last();
+
+         colMesh->mesh.setTransform(&mObjToWorld, mObjScale);
+         colMesh->mesh.setObject(this);
+
+         mShapeInstance->buildPolyListOpcode(mCollisionDetails[i], &colMesh->mesh, box);
+
+         colMesh->colMeshName = String::ToString("ColMesh%d-1", exportData->colMeshes.size());
+      }
+   }
+
+   //Next, process the LOD levels and materials.
+   if (isServerObject() && getClientObject())
+   {
+      TSStatic* clientShape = dynamic_cast<TSStatic*>(getClientObject());
+      U32 numDetails = clientShape->mShapeInstance->getNumDetails() - 1;
+
+      exportData->meshData.increment();
+
+      //Prep a meshData for this shape in particular
+      ColladaUtils::ExportData::meshLODData* meshData = &exportData->meshData.last();
+
+      //Fill out the info we'll need later to actually append our mesh data for the detail levels during the processing phase
+      meshData->shapeInst = clientShape->mShapeInstance;
+      meshData->originatingObject = this;
+      meshData->meshTransform = mObjToWorld;
+      meshData->scale = mObjScale;
+
+      //Iterate over all our detail levels
+      for (U32 i = 0; i < clientShape->mShapeInstance->getNumDetails(); i++)
+      {
+         TSShape::Detail detail = clientShape->mShapeInstance->getShape()->details[i];
+
+         String detailName = String::ToLower(clientShape->mShapeInstance->getShape()->getName(detail.nameIndex));
+
+         //Skip it if it's a collision or line of sight element
+         if (detailName.startsWith("col") || detailName.startsWith("los"))
+            continue;
+
+         meshData->meshDetailLevels.increment();
+
+         ColladaUtils::ExportData::detailLevel* curDetail = &meshData->meshDetailLevels.last();
+
+         //Make sure we denote the size this detail level has
+         curDetail->size = detail.size;
+      }
+   }
+
+   return true;
+}
+
 void TSStatic::buildConvex(const Box3F& box, Convex* convex)
 {
    if ( mCollisionType == None )
@@ -1279,6 +1370,16 @@ void TSStatic::onUnmount( SceneObject *obj, S32 node )
    _updateShouldTick();
 }
 
+U32 TSStatic::getNumDetails()
+{
+	if (isServerObject() && getClientObject())
+	{
+		TSStatic* clientShape = dynamic_cast<TSStatic*>(getClientObject());
+		return clientShape->mShapeInstance->getNumDetails();
+	}
+	return 0;
+};
+
 //------------------------------------------------------------------------
 //These functions are duplicated in tsStatic and shapeBase.
 //They each function a little differently; but achieve the same purpose of gathering

+ 3 - 0
Engine/source/T3D/tsStatic.h

@@ -138,6 +138,7 @@ protected:
    bool castRay(const Point3F &start, const Point3F &end, RayInfo* info);
    bool castRayRendered(const Point3F &start, const Point3F &end, RayInfo* info);
    bool buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F &box, const SphereF& sphere);
+   bool buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &);
    void buildConvex(const Box3F& box, Convex* convex);
    
    bool _createShape();
@@ -237,6 +238,8 @@ public:
   
    TSShapeInstance* getShapeInstance() const { return mShapeInstance; }
 
+   U32 getNumDetails();
+
    const Vector<S32>& getCollisionDetails() const { return mCollisionDetails; }
 
    const Vector<S32>& getLOSDetails() const { return mLOSDetails; }

+ 3 - 2
Engine/source/afx/afxMagicMissile.cpp

@@ -446,8 +446,9 @@ bool afxMagicMissileData::onAdd()
       Vector<char*> dataBlocks(__FILE__, __LINE__);
 
       // make a copy of points_string
-      char* tokCopy = new char[dStrlen(wiggle_axis_string) + 1];
-      dStrcpy(tokCopy, wiggle_axis_string);
+      dsize_t tokCopyLen = dStrlen(wiggle_axis_string) + 1;
+      char* tokCopy = new char[tokCopyLen];
+      dStrcpy(tokCopy, wiggle_axis_string, tokCopyLen);
 
       // extract tokens one by one, adding them to dataBlocks
       char* currTok = dStrtok(tokCopy, " \t");

+ 3 - 3
Engine/source/afx/arcaneFX.cpp

@@ -908,7 +908,7 @@ ConsoleFunction(echoThru, const char*, 2, 0, "(string passthru, string text...)"
    char *ret = Con::getReturnBuffer(len + 1);
    ret[0] = 0;
    for(i = 2; i < argc; i++)
-      dStrcat(ret, argv[i]);
+      dStrcat(ret, argv[i], len + 1);
 
    Con::printf("%s -- [%s]", ret, argv[1].getStringValue());
    ret[0] = 0;
@@ -928,7 +928,7 @@ ConsoleFunction(warnThru, const char*, 2, 0, "(string passthru, string text...)"
    char *ret = Con::getReturnBuffer(len + 1);
    ret[0] = 0;
    for(i = 2; i < argc; i++)
-      dStrcat(ret, argv[i]);
+      dStrcat(ret, argv[i], len + 1);
 
    Con::warnf("%s -- [%s]", ret, argv[1].getStringValue());
    ret[0] = 0;
@@ -948,7 +948,7 @@ ConsoleFunction(errorThru, const char*, 2, 0, "(string passthru, string text...)
    char *ret = Con::getReturnBuffer(len + 1);
    ret[0] = 0;
    for(i = 2; i < argc; i++)
-      dStrcat(ret, argv[i]);
+      dStrcat(ret, argv[i], len + 1);
 
    Con::errorf("%s -- [%s]", ret, argv[1].getStringValue());
    ret[0] = 0;

+ 1 - 1
Engine/source/afx/ce/afxAudioBank.cpp

@@ -184,7 +184,7 @@ void afxAudioBank::packData(BitStream* stream)
   if(!mFilename)
     buffer[0] = 0;
   else
-    dStrcpy(buffer, mFilename);
+    dStrcpy(buffer, mFilename, 256);
   stream->writeString(buffer);
   */
 

+ 9 - 6
Engine/source/afx/ce/afxParticleEmitter.cpp

@@ -141,8 +141,9 @@ bool afxParticleEmitterData::onAdd()
   if (tpaths_string != ST_NULLSTRING) 
   {
     Vector<char*> dataBlocks(__FILE__, __LINE__);
-    char* tokCopy = new char[dStrlen(tpaths_string) + 1];
-    dStrcpy(tokCopy, tpaths_string);
+    dsize_t tokCopyLen = dStrlen(tpaths_string) + 1;
+    char* tokCopy = new char[tokCopyLen];
+    dStrcpy(tokCopy, tpaths_string, tokCopyLen);
     
     char* currTok = dStrtok(tokCopy, " \t");
     while (currTok != NULL) 
@@ -467,8 +468,9 @@ bool afxParticleEmitterPathData::onAdd()
   if (epaths_string != ST_NULLSTRING) 
   {
     Vector<char*> dataBlocks(__FILE__, __LINE__);
-    char* tokCopy = new char[dStrlen(epaths_string) + 1];
-    dStrcpy(tokCopy, epaths_string);
+    dsize_t tokCopyLen = dStrlen(epaths_string) + 1;
+    char* tokCopy = new char[tokCopyLen];
+    dStrcpy(tokCopy, epaths_string, tokCopyLen);
 
     char* currTok = dStrtok(tokCopy, " \t");
     while (currTok != NULL) 
@@ -552,8 +554,9 @@ void afxParticleEmitterPathData::onPerformSubstitutions()
   if (epaths_string != ST_NULLSTRING) 
   {
     Vector<char*> dataBlocks(__FILE__, __LINE__);
-    char* tokCopy = new char[dStrlen(epaths_string) + 1];
-    dStrcpy(tokCopy, epaths_string);
+    dsize_t tokCopyLen = dStrlen(epaths_string) + 1;
+    char* tokCopy = new char[tokCopyLen];
+    dStrcpy(tokCopy, epaths_string, tokCopyLen);
 
     char* currTok = dStrtok(tokCopy, " \t");
     while (currTok != NULL) 

+ 3 - 3
Engine/source/afx/ea/afxEA_PhraseEffect.cpp

@@ -272,10 +272,10 @@ void afxEA_PhraseEffect::trigger_new_phrase()
   if (phrase_fx_data->on_trig_cmd != ST_NULLSTRING)
   {
     char obj_str[32];
-    dStrcpy(obj_str, Con::getIntArg(choreographer->getId()));
+    dStrcpy(obj_str, Con::getIntArg(choreographer->getId()), 32);
 
     char index_str[32];
-    dStrcpy(index_str, Con::getIntArg(group_index));
+    dStrcpy(index_str, Con::getIntArg(group_index), 32);
 
     char buffer[1024];
     char* b = buffer;
@@ -382,4 +382,4 @@ bool afxEA_PhraseEffectDesc::requiresStop(const afxEffectWrapperData* ew, const
   return (timing.lifetime < 0);
 }
 
-//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
+//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

+ 5 - 5
Engine/source/afx/rpg/afxRPGMagicSpell.cpp

@@ -194,7 +194,7 @@ char* afxRPGMagicSpellData::fmt_placeholder_desc(char* buffer, int len) const
 {
   char pack_str[32]; 
   if (source_pack == ST_NULLSTRING)
-    dStrcpy(pack_str, "unknown");
+    dStrcpy(pack_str, "unknown", 32);
   else
     dSprintf(pack_str, 32, "%s", source_pack);
 
@@ -225,9 +225,9 @@ char* afxRPGMagicSpellData::formatDesc(char* buffer, int len) const
     {
       if (spell_target != TARGET_NOTHING)
       {
-        dStrcpy(target_str, _afxRPGMagicSpell_TargetType::_sEnumTable[i].mName);
+        dStrcpy(target_str, _afxRPGMagicSpell_TargetType::_sEnumTable[i].mName, 32);
         if (spell_target != TARGET_FREE && target_optional)
-          dStrcat(target_str, " (opt)");
+          dStrcat(target_str, " (opt)", 32);
       }
       break;
     }
@@ -245,13 +245,13 @@ char* afxRPGMagicSpellData::formatDesc(char* buffer, int len) const
 
   char casting_str[32];
   if (casting_dur <= 0)
-    dStrcpy(casting_str, "instant");
+    dStrcpy(casting_str, "instant", 32);
   else
     dSprintf(casting_str, 32, "%.1f sec cast", casting_dur);
 
   char pack_str[32]; 
   if (source_pack == ST_NULLSTRING)
-    dStrcpy(pack_str, "unknown");
+    dStrcpy(pack_str, "unknown", 32);
   else
     dSprintf(pack_str, 32, "%s", source_pack);
 

+ 9 - 7
Engine/source/afx/ui/afxSpellButton.cpp

@@ -171,10 +171,11 @@ void afxSpellButton::setBitmap(const char *name, bool placeholder)
 
     if (placeholder)
     {
-      dStrcpy(buffer, name);
+      dStrcpy(buffer, name, 1024);
+      S32 pLen = 1024 - dStrlen(buffer);
       p = buffer + dStrlen(buffer);
     
-      dStrcpy(p, "_i");
+      dStrcpy(p, "_i", pLen);
       mTextureInactive.set(buffer, COOLDOWN_PROFILE);
       mTextureNormal = mTextureInactive;
       mTextureHilight = mTextureInactive;
@@ -183,19 +184,20 @@ void afxSpellButton::setBitmap(const char *name, bool placeholder)
     }
     else
     {
-      dStrcpy(buffer, name);
+      dStrcpy(buffer, name, 1024);
+      S32 pLen = 1024 - dStrlen(buffer);
       p = buffer + dStrlen(buffer);   
-      dStrcpy(p, "_n");
+      dStrcpy(p, "_n", pLen);
       mTextureNormal.set(buffer, COOLDOWN_PROFILE);
-      dStrcpy(p, "_h");
+      dStrcpy(p, "_h", pLen);
       mTextureHilight.set(buffer, COOLDOWN_PROFILE);
       if (!mTextureHilight)
         mTextureHilight = mTextureNormal;
-      dStrcpy(p, "_d");
+      dStrcpy(p, "_d", pLen);
       mTextureDepressed.set(buffer, COOLDOWN_PROFILE);
       if (!mTextureDepressed)
         mTextureDepressed = mTextureHilight;
-      dStrcpy(p, "_i");
+      dStrcpy(p, "_i", pLen);
       mTextureInactive.set(buffer, COOLDOWN_PROFILE);
       if (!mTextureInactive)
         mTextureInactive = mTextureNormal;

+ 3 - 2
Engine/source/afx/xm/afxXM_PathConform.cpp

@@ -194,8 +194,9 @@ bool afxXM_PathConformData::onAdd()
   if (paths_string != ST_NULLSTRING) 
   {
     Vector<char*> dataBlocks(__FILE__, __LINE__);
-    char* tokCopy = new char[dStrlen(paths_string) + 1];
-    dStrcpy(tokCopy, paths_string);
+    dsize_t tokCopyLen = dStrlen(paths_string) + 1;
+    char* tokCopy = new char[tokCopyLen];
+    dStrcpy(tokCopy, paths_string, tokCopyLen);
     
     char* currTok = dStrtok(tokCopy, " \t");
     while (currTok != NULL) 

+ 5 - 4
Engine/source/app/badWordFilter.cpp

@@ -50,7 +50,7 @@ BadWordFilter::BadWordFilter()
 {
    VECTOR_SET_ASSOCIATION( filterTables );
 
-   dStrcpy(defaultReplaceStr, "knqwrtlzs");
+   dStrcpy(defaultReplaceStr, "knqwrtlzs", 32);
    filterTables.push_back(new FilterTable);
    curOffset = 0;
 }
@@ -147,7 +147,7 @@ bool BadWordFilter::setDefaultReplaceStr(const char *str)
    U32 len = dStrlen(str);
    if(len < 2 || len >= sizeof(defaultReplaceStr))
       return false;
-   dStrcpy(defaultReplaceStr, str);
+   dStrcpy(defaultReplaceStr, str, 32);
    return true;
 }
 
@@ -286,8 +286,9 @@ DefineEngineFunction(filterString, const char *, (const char* baseString, const
    else
       replaceStr = gBadWordFilter->getDefaultReplaceStr();
 
-   char *ret = Con::getReturnBuffer(dStrlen(baseString) + 1);
-   dStrcpy(ret, baseString);
+   dsize_t retLen = dStrlen(baseString) + 1;
+   char *ret = Con::getReturnBuffer(retLen);
+   dStrcpy(ret, baseString, retLen);
    gBadWordFilter->filterString(ret, replaceStr);
    return ret;
 }

+ 1 - 1
Engine/source/app/banList.cpp

@@ -86,7 +86,7 @@ void BanList::addBan(S32 uniqueId, const char *TA, S32 banTime)
    }
 
    BanInfo b;
-   dStrcpy(b.transportAddress, TA);
+   dStrcpy(b.transportAddress, TA, 128);
    b.uniqueId = uniqueId;
    b.bannedUntil = banTime;
 

+ 1 - 1
Engine/source/app/mainLoop.cpp

@@ -495,7 +495,7 @@ bool StandardMainLoop::handleCommandLine( S32 argc, const char **argv )
          S32 pathLen = dStrlen( fdd.mFile );
          FrameTemp<char> szPathCopy( pathLen + 1);
 
-         dStrcpy( szPathCopy, fdd.mFile );
+         dStrcpy( szPathCopy, fdd.mFile, pathLen + 1 );
          //forwardslash( szPathCopy );
 
          const char *path = dStrrchr(szPathCopy, '/');

+ 5 - 5
Engine/source/app/net/net.cpp

@@ -128,8 +128,8 @@
       const char *rmtCommandName = dStrchr(mArgv[1], ' ') + 1;
       if(conn->isConnectionToServer())
       {
-         dStrcpy(mBuf, "clientCmd");
-         dStrcat(mBuf, rmtCommandName);
+         dStrcpy(mBuf, "clientCmd", 1024);
+         dStrcat(mBuf, rmtCommandName, 1024);
 
          char *temp = mArgv[1];
          mArgv[1] = mBuf;
@@ -139,8 +139,8 @@
       }
       else
       {
-         dStrcpy(mBuf, "serverCmd");
-         dStrcat(mBuf, rmtCommandName);
+         dStrcpy(mBuf, "serverCmd", 1024);
+         dStrcat(mBuf, rmtCommandName, 1024);
          char *temp = mArgv[1];
 
          dSprintf(idBuf, sizeof(idBuf), "%d", conn->getId());
@@ -409,7 +409,7 @@ ConsoleFunction( buildTaggedString, const char*, 2, 11, "(string format, ...)"
             S32 strLength = dStrlen(argStr);
             if (strLength > strMaxLength)
                goto done;
-            dStrcpy(strBufPtr, argStr);
+            dStrcpy(strBufPtr, argStr, strMaxLength);
             strBufPtr += strLength;
             strMaxLength -= strLength;
             fmtStrPtr += 2;

+ 2 - 2
Engine/source/app/net/netExamples.cpp

@@ -110,7 +110,7 @@ public:
    SimpleNetObject()
    {
       mNetFlags.set(ScopeAlways | Ghostable);
-      dStrcpy(message, "Hello World!");
+      dStrcpy(message, "Hello World!", 256);
    }
    U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
    {
@@ -125,7 +125,7 @@ public:
    void setMessage(const char *msg)
    {
       setMaskBits(1);
-      dStrcpy(message, msg);
+      dStrcpy(message, msg, 256);
    }
 
    DECLARE_CONOBJECT(SimpleNetObject);

+ 41 - 30
Engine/source/app/net/serverQuery.cpp

@@ -394,12 +394,12 @@ void queryLanServers(U32 port, U8 flags, const char* gameType, const char* missi
       if ( !sActiveFilter.gameType || dStricmp( sActiveFilter.gameType, "Any" ) != 0 )
       {
          sActiveFilter.gameType = (char*) dRealloc( sActiveFilter.gameType, 4 );
-         dStrcpy( sActiveFilter.gameType, "Any" );
+         dStrcpy( sActiveFilter.gameType, "Any", 4 );
       }
       if ( !sActiveFilter.missionType || dStricmp( sActiveFilter.missionType, "Any" ) != 0 )
       {
          sActiveFilter.missionType = (char*) dRealloc( sActiveFilter.missionType, 4 );
-         dStrcpy( sActiveFilter.missionType, "Any" );
+         dStrcpy( sActiveFilter.missionType, "Any", 4 );
       }
       sActiveFilter.queryFlags   = 0;
    sActiveFilter.minPlayers   = minPlayers;
@@ -510,14 +510,16 @@ void queryMasterServer(U8 flags, const char* gameType, const char* missionType,
       // Update the active filter:
       if ( !sActiveFilter.gameType || dStrcmp( sActiveFilter.gameType, gameType ) != 0 )
       {
-         sActiveFilter.gameType = (char*) dRealloc( sActiveFilter.gameType, dStrlen( gameType ) + 1 );
-         dStrcpy( sActiveFilter.gameType, gameType );
+         dsize_t gameTypeLen = dStrlen(gameType) + 1;
+         sActiveFilter.gameType = (char*) dRealloc( sActiveFilter.gameType, gameTypeLen );
+         dStrcpy( sActiveFilter.gameType, gameType, gameTypeLen );
       }
 
       if ( !sActiveFilter.missionType || dStrcmp( sActiveFilter.missionType, missionType ) != 0 )
       {
-         sActiveFilter.missionType = (char*) dRealloc( sActiveFilter.missionType, dStrlen( missionType ) + 1 );
-         dStrcpy( sActiveFilter.missionType, missionType );
+         dsize_t missionTypeLen = dStrlen(missionType) + 1;
+         sActiveFilter.missionType = (char*) dRealloc( sActiveFilter.missionType, missionTypeLen );
+         dStrcpy( sActiveFilter.missionType, missionType, missionTypeLen );
       }
 
       sActiveFilter.queryFlags   = flags | ServerFilter::NewStyleResponse;
@@ -969,8 +971,9 @@ static void pushServerFavorites()
             Net::stringToAddress( addrString, &addr );
             ServerInfo* si = findOrCreateServerInfo( &addr );
             AssertFatal(si, "pushServerFavorites - failed to create Server Info!" );
-            si->name = (char*) dRealloc( (void*) si->name, dStrlen( serverName ) + 1 );
-            dStrcpy( si->name, serverName );
+            dsize_t nameLen = dStrlen(serverName) + 1;
+            si->name = (char*) dRealloc( (void*) si->name, nameLen );
+            dStrcpy( si->name, serverName, nameLen );
             si->isFavorite = true;
             pushPingRequest( &addr );
          }
@@ -1053,14 +1056,15 @@ void addFakeServers( S32 howMany )
       newServer.maxPlayers = 64;
       char buf[256];
       dSprintf( buf, 255, "Fake server #%d", sNumFakeServers );
-      newServer.name = (char*) dMalloc( dStrlen( buf ) + 1 );
-      dStrcpy( newServer.name, buf );
+      dsize_t nameLen = dStrlen(buf) + 1;
+      newServer.name = (char*) dMalloc( nameLen );
+      dStrcpy( newServer.name, buf, nameLen );
       newServer.gameType = (char*) dMalloc( 5 );
-      dStrcpy( newServer.gameType, "Fake" );
-      newServer.missionType = (char*) dMalloc( 4 );
-      dStrcpy( newServer.missionType, "FakeMissionType" );
+      dStrcpy( newServer.gameType, "Fake", 5 );
+      newServer.missionType = (char*) dMalloc( 16 );
+      dStrcpy( newServer.missionType, "FakeMissionType", 16 );
       newServer.missionName = (char*) dMalloc( 14 );
-      dStrcpy( newServer.missionName, "FakeMapName" );
+      dStrcpy( newServer.missionName, "FakeMapName", 14 );
       Net::stringToAddress( "IP:198.74.33.35:28000", &newServer.address );
       newServer.ping = (U32)( Platform::getRandom() * 200.0f );
       newServer.cpuSpeed = 470;
@@ -1353,9 +1357,9 @@ static void processPingsAndQueries( U32 session, bool schedule )
       char msg[64];
       U32 foundCount = gServerList.size();
       if ( foundCount == 0 )
-         dStrcpy( msg, "No servers found." );
+         dStrcpy( msg, "No servers found.", 64 );
       else if ( foundCount == 1 )
-         dStrcpy( msg, "One server found." );
+         dStrcpy( msg, "One server found.", 64 );
       else
          dSprintf( msg, sizeof( msg ), "%d servers found.", foundCount );
 
@@ -1753,8 +1757,9 @@ static void handleGameMasterInfoRequest( const NetAddress* address, U32 key, U8
       out->write( playerCount );
 
       const char* guidList = Con::getVariable( "Server::GuidList" );
-      char* buf = new char[dStrlen( guidList ) + 1];
-      dStrcpy( buf, guidList );
+      dsize_t bufLen = dStrlen(guidList) + 1;
+      char* buf = new char[bufLen];
+      dStrcpy( buf, guidList, bufLen );
       char* temp = dStrtok( buf, "\t" );
       temp8 = 0;
       for ( ; temp && temp8 < playerCount; temp8++ )
@@ -1948,8 +1953,9 @@ static void handleGamePingResponse( const NetAddress* address, BitStream* stream
    stream->readString( buf );
    if ( !si->name )
    {
-      si->name = (char*) dMalloc( dStrlen( buf ) + 1 );
-      dStrcpy( si->name, buf );
+      dsize_t bufLen = dStrlen(buf) + 1;
+      si->name = (char*) dMalloc(bufLen);
+      dStrcpy( si->name, buf, bufLen );
    }
 
    // Set the server up to be queried:
@@ -2050,8 +2056,9 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream
    stream->readString( stringBuf );
    if ( !si->gameType || dStricmp( si->gameType, stringBuf ) != 0 )
    {
-      si->gameType = (char*) dRealloc( (void*) si->gameType, dStrlen( stringBuf ) + 1 );
-      dStrcpy( si->gameType, stringBuf );
+      dsize_t gameTypeLen = dStrlen(stringBuf) + 1;
+      si->gameType = (char*) dRealloc( (void*) si->gameType, gameTypeLen );
+      dStrcpy( si->gameType, stringBuf, gameTypeLen );
 
       // Test against the active filter:
       if ( applyFilter && dStricmp( sActiveFilter.gameType, "any" ) != 0
@@ -2067,8 +2074,9 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream
    stream->readString( stringBuf );
    if ( !si->missionType || dStrcmp( si->missionType, stringBuf ) != 0 )
    {
-      si->missionType = (char*) dRealloc( (void*) si->missionType, dStrlen( stringBuf ) + 1 );
-      dStrcpy( si->missionType, stringBuf );
+      dsize_t missionTypeLen = dStrlen(stringBuf) + 1;
+      si->missionType = (char*) dRealloc( (void*) si->missionType, missionTypeLen );
+      dStrcpy( si->missionType, stringBuf, missionTypeLen );
 
       // Test against the active filter:
       if ( applyFilter && dStricmp( sActiveFilter.missionType, "any" ) != 0
@@ -2088,8 +2096,9 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream
       *temp = '\0';
    if ( !si->missionName || dStrcmp( si->missionName, stringBuf ) != 0 )
    {
-      si->missionName = (char*) dRealloc( (void*) si->missionName, dStrlen( stringBuf ) + 1 );
-      dStrcpy( si->missionName, stringBuf );
+      dsize_t missionNameLen = dStrlen(stringBuf) + 1;
+      si->missionName = (char*) dRealloc( (void*) si->missionName, missionNameLen );
+      dStrcpy( si->missionName, stringBuf, missionNameLen );
    }
 
    // Get the server status:
@@ -2157,16 +2166,18 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream
    stream->readString( stringBuf );
    if ( !si->statusString || ( isUpdate && dStrcmp( si->statusString, stringBuf ) != 0 ) )
    {
-      si->infoString = (char*) dRealloc( (void*) si->infoString, dStrlen( stringBuf ) + 1 );
-      dStrcpy( si->infoString, stringBuf );
+      dsize_t infoLen = dStrlen(stringBuf) + 1;
+      si->infoString = (char*) dRealloc( (void*) si->infoString, infoLen );
+      dStrcpy( si->infoString, stringBuf, infoLen );
    }
 
    // Get the content string:
    readLongCString( stream, stringBuf );
    if ( !si->statusString || ( isUpdate && dStrcmp( si->statusString, stringBuf ) != 0 ) )
    {
-      si->statusString = (char*) dRealloc( (void*) si->statusString, dStrlen( stringBuf ) + 1 );
-      dStrcpy( si->statusString, stringBuf );
+      dsize_t statusLen = dStrlen(stringBuf) + 1;
+      si->statusString = (char*) dRealloc( (void*) si->statusString, statusLen );
+      dStrcpy( si->statusString, stringBuf, statusLen );
    }
 
    // Update the server browser gui!

+ 3 - 2
Engine/source/cinterface/cinterface.cpp

@@ -182,8 +182,9 @@ extern "C" {
 
 	void torque_setexecutablepath(const char* directory)
 	{
-		gExecutablePath = new char[strlen(directory)+1];
-		strcpy(gExecutablePath, directory);
+		dsize_t pathLen = dStrlen(directory) + 1;
+		gExecutablePath = new char[pathLen];
+		dStrcpy(gExecutablePath, directory, pathLen);
 	} 
 
    // set Torque 3D into web deployment mode (disable fullscreen exlusive mode, etc)

+ 3 - 2
Engine/source/console/CMDscan.cpp

@@ -2340,8 +2340,9 @@ static int Sc_ScanString(int ret)
    if (!collapseEscape(CMDtext + 1))
       return -1;
 
-   char* buffer = (char*)consoleAlloc(dStrlen(CMDtext));
-   dStrcpy(buffer, CMDtext + 1);
+   dsize_t bufferLen = dStrlen(CMDtext);
+   char* buffer = (char*)consoleAlloc(bufferLen);
+   dStrcpy(buffer, CMDtext + 1, bufferLen);
 
    CMDlval.str = MakeToken< char* >(buffer, lineIndex);
    return ret;

+ 6 - 5
Engine/source/console/CMDscan.l

@@ -71,7 +71,7 @@ inline int isatty(int) { return 0; }
          buf[n++] = (char) c; \
       result = n; \
    }
-   
+
 // General helper stuff.
 static int lineIndex;
 
@@ -411,10 +411,11 @@ static int Sc_ScanString(int ret)
    CMDtext[CMDleng - 1] = 0;
    if(!collapseEscape(CMDtext+1))
       return -1;
-      
-   char* buffer = ( char* ) consoleAlloc( dStrlen( CMDtext ) );
-   dStrcpy( buffer, CMDtext + 1 );
-   
+
+   dsize_t bufferLen = dStrlen( CMDtext );
+   char* buffer = ( char* ) consoleAlloc( bufferLen );
+   dStrcpy( buffer, CMDtext + 1, bufferLen );
+
    CMDlval.str = MakeToken< char* >( buffer, lineIndex );
    return ret;
 }

+ 2 - 2
Engine/source/console/SimXMLDocument.cpp

@@ -833,7 +833,7 @@ void SimXMLDocument::setObjectAttributes(const char* objectID)
             continue;
 
          FrameTemp<char> valCopy( dStrlen( val ) + 1 );
-         dStrcpy( (char *)valCopy, val );
+         dStrcpy( (char *)valCopy, val, valCopy.size() );
 
          if (!pObject->writeField(itr->pFieldname, valCopy))
             continue;
@@ -873,7 +873,7 @@ void SimXMLDocument::setObjectAttributes(const char* objectID)
    //      continue;
 
    //   FrameTemp<char> valCopy( dStrlen( val ) + 1 );
-   //   dStrcpy( (char *)valCopy, val );
+   //   dStrcpy( (char *)valCopy, val, valCopy.size() );
 
    //   if (!pObject->writeField(itr->pFieldname, valCopy))
    //      continue;

+ 3 - 2
Engine/source/console/astAlloc.cpp

@@ -238,10 +238,11 @@ StrConstNode *StrConstNode::alloc(S32 lineNumber, char *str, bool tag, bool doc)
    StrConstNode *ret = (StrConstNode *)consoleAlloc(sizeof(StrConstNode));
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
-   ret->str = (char *)consoleAlloc(dStrlen(str) + 1);
+   dsize_t retStrLen = dStrlen(str) + 1;
+   ret->str = (char *)consoleAlloc(retStrLen);
    ret->tag = tag;
    ret->doc = doc;
-   dStrcpy(ret->str, str);
+   dStrcpy(ret->str, str, retStrLen);
 
    return ret;
 }

+ 22 - 26
Engine/source/console/codeInterpreter.cpp

@@ -95,19 +95,17 @@ static void getFieldComponent(SimObject* object, StringTableEntry field, const c
 
       // Translate xyzw and rgba into the indexed component 
       // of the variable or field.
-      //
-      // Review: Should we use strncpy to prevent a buffer overflow?
       if (subField == xyzw[0] || subField == rgba[0])
-         dStrcpy(val, StringUnit::getUnit(prevVal, 0, " \t\n"));
+         dStrcpy(val, StringUnit::getUnit(prevVal, 0, " \t\n"), 128);
 
       else if (subField == xyzw[1] || subField == rgba[1])
-         dStrcpy(val, StringUnit::getUnit(prevVal, 1, " \t\n"));
+         dStrcpy(val, StringUnit::getUnit(prevVal, 1, " \t\n"), 128);
 
       else if (subField == xyzw[2] || subField == rgba[2])
-         dStrcpy(val, StringUnit::getUnit(prevVal, 2, " \t\n"));
+         dStrcpy(val, StringUnit::getUnit(prevVal, 2, " \t\n"), 128);
 
       else if (subField == xyzw[3] || subField == rgba[3])
-         dStrcpy(val, StringUnit::getUnit(prevVal, 3, " \t\n"));
+         dStrcpy(val, StringUnit::getUnit(prevVal, 3, " \t\n"), 128);
 
       else
          val[0] = 0;
@@ -157,19 +155,17 @@ static void setFieldComponent(SimObject* object, StringTableEntry field, const c
 
    // Insert the value into the specified 
    // component of the string.
-   //
-   // Review: Should we use strncpy to prevent a buffer overflow?
    if (subField == xyzw[0] || subField == rgba[0])
-      dStrcpy(val, StringUnit::setUnit(prevVal, 0, strValue, " \t\n"));
+      dStrcpy(val, StringUnit::setUnit(prevVal, 0, strValue, " \t\n"), 128);
 
    else if (subField == xyzw[1] || subField == rgba[1])
-      dStrcpy(val, StringUnit::setUnit(prevVal, 1, strValue, " \t\n"));
+      dStrcpy(val, StringUnit::setUnit(prevVal, 1, strValue, " \t\n"), 128);
 
    else if (subField == xyzw[2] || subField == rgba[2])
-      dStrcpy(val, StringUnit::setUnit(prevVal, 2, strValue, " \t\n"));
+      dStrcpy(val, StringUnit::setUnit(prevVal, 2, strValue, " \t\n"), 128);
 
    else if (subField == xyzw[3] || subField == rgba[3])
-      dStrcpy(val, StringUnit::setUnit(prevVal, 3, strValue, " \t\n"));
+      dStrcpy(val, StringUnit::setUnit(prevVal, 3, strValue, " \t\n"), 128);
 
    if (val[0] != 0)
    {
@@ -420,13 +416,13 @@ exitLabel:
       if (gEvalState.traceOn)
       {
          sTraceBuffer[0] = 0;
-         dStrcat(sTraceBuffer, "Leaving ");
+         dStrcat(sTraceBuffer, "Leaving ", 1024);
 
          if (packageName)
          {
-            dStrcat(sTraceBuffer, "[");
-            dStrcat(sTraceBuffer, packageName);
-            dStrcat(sTraceBuffer, "]");
+            dStrcat(sTraceBuffer, "[", 1024);
+            dStrcat(sTraceBuffer, packageName, 1024);
+            dStrcat(sTraceBuffer, "]", 1024);
          }
          if (thisNamespace && thisNamespace->mName)
          {
@@ -471,13 +467,13 @@ void CodeInterpreter::parseArgs(U32 &ip)
       if (gEvalState.traceOn)
       {
          sTraceBuffer[0] = 0;
-         dStrcat(sTraceBuffer, "Entering ");
+         dStrcat(sTraceBuffer, "Entering ", 1024);
 
          if (mExec.packageName)
          {
-            dStrcat(sTraceBuffer, "[");
-            dStrcat(sTraceBuffer, mExec.packageName);
-            dStrcat(sTraceBuffer, "]");
+            dStrcat(sTraceBuffer, "[", 1024);
+            dStrcat(sTraceBuffer, mExec.packageName, 1024);
+            dStrcat(sTraceBuffer, "]", 1024);
          }
          if (mExec.thisNamespace && mExec.thisNamespace->mName)
          {
@@ -491,11 +487,11 @@ void CodeInterpreter::parseArgs(U32 &ip)
          }
          for (S32 i = 0; i < wantedArgc; i++)
          {
-            dStrcat(sTraceBuffer, mExec.argv[i + 1]);
+            dStrcat(sTraceBuffer, mExec.argv[i + 1], 1024);
             if (i != wantedArgc - 1)
-               dStrcat(sTraceBuffer, ", ");
+               dStrcat(sTraceBuffer, ", ", 1024);
          }
-         dStrcat(sTraceBuffer, ")");
+         dStrcat(sTraceBuffer, ")", 1024);
          Con::printf("%s", sTraceBuffer);
       }
 
@@ -1729,7 +1725,7 @@ OPCodeReturn CodeInterpreter::op_setcurfield(U32 &ip)
 {
    // Save the previous field for parsing vector fields.
    mPrevField = mCurField;
-   dStrcpy(prevFieldArray, curFieldArray);
+   dStrcpy(prevFieldArray, curFieldArray, 256);
    mCurField = CodeToSTE(mCodeBlock->code, ip);
    curFieldArray[0] = 0;
    ip += 2;
@@ -1738,7 +1734,7 @@ OPCodeReturn CodeInterpreter::op_setcurfield(U32 &ip)
 
 OPCodeReturn CodeInterpreter::op_setcurfield_array(U32 &ip)
 {
-   dStrcpy(curFieldArray, STR.getStringValue());
+   dStrcpy(curFieldArray, STR.getStringValue(), 256);
    return OPCodeReturn::success;
 }
 
@@ -1771,7 +1767,7 @@ OPCodeReturn CodeInterpreter::op_setcurfield_this(U32 &ip)
    mCurObject = mThisObject;
 
    mPrevField = mCurField;
-   dStrcpy(prevFieldArray, curFieldArray);
+   dStrcpy(prevFieldArray, curFieldArray, 256);
    mCurField = CodeToSTE(mCodeBlock->code, ip);
    curFieldArray[0] = 0;
    ip += 2;

+ 2 - 2
Engine/source/console/compiledEval.cpp

@@ -70,9 +70,9 @@ namespace Con
       ret[0] = 0;
       for (walk = ns; walk; walk = walk->mParent)
       {
-         dStrcat(ret, walk->mName);
+         dStrcat(ret, walk->mName, size);
          if (walk->mParent)
-            dStrcat(ret, " -> ");
+            dStrcat(ret, " -> ", size);
       }
       return ret;
    }

+ 2 - 2
Engine/source/console/compiler.cpp

@@ -164,7 +164,7 @@ U32 CompilerStringTable::add(const char *str, bool caseSens, bool tag)
    newStr->string = (char *)consoleAlloc(len);
    newStr->len = len;
    newStr->tag = tag;
-   dStrcpy(newStr->string, str);
+   dStrcpy(newStr->string, str, len);
 
    // Put into the hash table.
    hashTable[str] = newStr;
@@ -195,7 +195,7 @@ char *CompilerStringTable::build()
    char *ret = new char[totalLen];
    dMemset(ret, 0, totalLen);
    for (Entry *walk = list; walk; walk = walk->next)
-      dStrcpy(ret + walk->start, walk->string);
+      dStrcpy(ret + walk->start, walk->string, totalLen - walk->start);
    return ret;
 }
 

+ 17 - 16
Engine/source/console/console.cpp

@@ -440,7 +440,7 @@ U32 tabComplete(char* inputBuffer, U32 cursorPos, U32 maxResultLength, bool forw
    {
       // If not...
       // Save it for checking next time.
-      dStrcpy(tabBuffer, inputBuffer);
+      dStrcpy(tabBuffer, inputBuffer, MaxCompletionBufferSize);
       // Scan backward from the cursor position to find the base to complete from.
       S32 p = cursorPos;
       while ((p > 0) && (inputBuffer[p - 1] != ' ') && (inputBuffer[p - 1] != '.') && (inputBuffer[p - 1] != '('))
@@ -527,7 +527,7 @@ U32 tabComplete(char* inputBuffer, U32 cursorPos, U32 maxResultLength, bool forw
    }
 
    // Save the modified input buffer for checking next time.
-   dStrcpy(tabBuffer, inputBuffer);
+   dStrcpy(tabBuffer, inputBuffer, MaxCompletionBufferSize);
 
    // Return the new (maybe) cursor position.
    return cursorPos;
@@ -646,8 +646,9 @@ static void _printf(ConsoleLogEntry::Level level, ConsoleLogEntry::Type type, co
             entry.mLevel  = level;
             entry.mType   = type;
 #ifndef TORQUE_SHIPPING // this is equivalent to a memory leak, turn it off in ship build            
-            entry.mString = (const char *)consoleLogChunker.alloc(dStrlen(pos) + 1);
-            dStrcpy(const_cast<char*>(entry.mString), pos);
+            dsize_t logStringLen = dStrlen(pos) + 1;
+            entry.mString = (const char *)consoleLogChunker.alloc(logStringLen);
+            dStrcpy(const_cast<char*>(entry.mString), pos, logStringLen);
             
             // This prevents infinite recursion if the console itself needs to
             // re-allocate memory to accommodate the new console log entry, and 
@@ -1271,7 +1272,7 @@ bool executeFile(const char* fileName, bool noCalls, bool journalScript)
       scriptFile = NULL;
 
       dsoModifiedTime = dsoFile->getModifiedTime();
-      dStrcpy(nameBuffer, scriptFileName);
+      dStrcpy(nameBuffer, scriptFileName, 512);
    }
 
    // If we're supposed to be compiling this file, check to see if there's a DSO
@@ -2097,12 +2098,12 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor
          if (ensureTrailingSlash)
          {
             // Yes, so ensure it.
-            Con::ensureTrailingSlash(pDstPath, pSrcPath);
+            Con::ensureTrailingSlash(pDstPath, pSrcPath, size);
          }
          else
          {
             // No, so just use the source path.
-            dStrcpy(pDstPath, pSrcPath);
+            dStrcpy(pDstPath, pSrcPath, size);
          }
 
          return false;
@@ -2118,7 +2119,7 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor
       if (ensureTrailingSlash)
       {
          // Yes, so ensure it.
-         Con::ensureTrailingSlash(pathBuffer, pathBuffer);
+         Con::ensureTrailingSlash(pathBuffer, pathBuffer, size);
       }
 
       // Strip repeat slashes.
@@ -2143,12 +2144,12 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor
          if (ensureTrailingSlash)
          {
             // Yes, so ensure it.
-            Con::ensureTrailingSlash(pDstPath, pSrcPath);
+            Con::ensureTrailingSlash(pDstPath, pSrcPath, size);
          }
          else
          {
             // No, so just use the source path.
-            dStrcpy(pDstPath, pSrcPath);
+            dStrcpy(pDstPath, pSrcPath, size);
          }
 
          return false;
@@ -2183,7 +2184,7 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor
       if (ensureTrailingSlash)
       {
          // Yes, so ensure it.
-         Con::ensureTrailingSlash(pathBuffer, pathBuffer);
+         Con::ensureTrailingSlash(pathBuffer, pathBuffer, size);
       }
 
       // Strip repeat slashes.
@@ -2208,7 +2209,7 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor
    if (ensureTrailingSlash)
    {
       // Yes, so ensure it.
-      Con::ensureTrailingSlash(pathBuffer, pathBuffer);
+      Con::ensureTrailingSlash(pathBuffer, pathBuffer, size);
    }
 
    // Strip repeat slashes.
@@ -2300,10 +2301,10 @@ void collapsePath(char* pDstPath, U32 size, const char* pSrcPath, const char* pW
 }
 
 
-void ensureTrailingSlash(char* pDstPath, const char* pSrcPath)
+void ensureTrailingSlash(char* pDstPath, const char* pSrcPath, S32 dstSize)
 {
    // Copy to target.
-   dStrcpy(pDstPath, pSrcPath);
+   dStrcpy(pDstPath, pSrcPath, dstSize);
 
    // Find trailing character index.
    S32 trailIndex = dStrlen(pDstPath);
@@ -2353,7 +2354,7 @@ StringTableEntry getDSOPath(const char *scriptPath)
    else
    {
       StringTableEntry strippedPath = Platform::stripBasePath(scriptPath);
-      dStrcpy(relPath, strippedPath);
+      dStrcpy(relPath, strippedPath, 1024);
 
       char *slash = dStrrchr(relPath, '/');
       if (slash)
@@ -2616,7 +2617,7 @@ const char *ConsoleValue::getStringValue()
       else if(newLen > bufferLen)
          sval = (char *) dRealloc(sval, newLen);
 
-      dStrcpy(sval, internalValue);
+      dStrcpy(sval, internalValue, newLen);
       bufferLen = newLen;
 
       return sval;

+ 1 - 1
Engine/source/console/console.h

@@ -491,7 +491,7 @@ namespace Con
    bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWorkingDirectoryHint = NULL, const bool ensureTrailingSlash = false);
    void collapsePath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWorkingDirectoryHint = NULL);
    bool isBasePath(const char* SrcPath, const char* pBasePath);
-   void ensureTrailingSlash(char* pDstPath, const char* pSrcPath);
+   void ensureTrailingSlash(char* pDstPath, const char* pSrcPath, S32 dstSize);
    bool stripRepeatSlashes(char* pDstPath, const char* pSrcPath, S32 dstSize);
    StringTableEntry getDSOPath(const char *scriptPath);
 

+ 2 - 2
Engine/source/console/consoleDoc.cpp

@@ -90,7 +90,7 @@ void printClassHeader(const char* usage, const char * className, const char * su
       // Copy Usage Document
       S32 usageLen = dStrlen( usage );
       FrameTemp<char> usageStr( usageLen );
-      dStrcpy( usageStr, usage );
+      dStrcpy( usageStr, usage, usageLen );
 
       // Print Header
       Con::printf( "/*!" );
@@ -117,7 +117,7 @@ void printClassHeader(const char* usage, const char * className, const char * su
          }
          
          // Copy line and update usagePtr
-         dStrcpy( lineStr, usagePtr );
+         dStrcpy( lineStr, usagePtr, 2048 );
          usagePtr = (newLine != NULL ) ? newLine : usagePtr;
          lineLen = dStrlen( lineStr );
 

+ 25 - 20
Engine/source/console/consoleFunctions.cpp

@@ -561,12 +561,13 @@ DefineConsoleFunction( stripChars, const char*, ( const char* str, const char* c
    "@endtsexample\n"
    "@ingroup Strings" )
 {
-   char* ret = Con::getReturnBuffer( dStrlen( str ) + 1 );
-   dStrcpy( ret, str );
+   S32 len = dStrlen(str) + 1;
+   char* ret = Con::getReturnBuffer( len );
+   dStrcpy( ret, str, len );
    U32 pos = dStrcspn( ret, chars );
    while ( pos < dStrlen( ret ) )
    {
-      dStrcpy( ret + pos, ret + pos + 1 );
+      dStrcpy( ret + pos, ret + pos + 1, len - pos );
       pos = dStrcspn( ret, chars );
    }
    return( ret );
@@ -584,8 +585,9 @@ DefineConsoleFunction( strlwr, const char*, ( const char* str ),,
    "@see strupr\n"
    "@ingroup Strings" )
 {
-   char *ret = Con::getReturnBuffer(dStrlen(str) + 1);
-   dStrcpy(ret, str);
+   dsize_t retLen = dStrlen(str) + 1;
+   char *ret = Con::getReturnBuffer(retLen);
+   dStrcpy(ret, str, retLen);
    return dStrlwr(ret);
 }
 
@@ -601,8 +603,9 @@ DefineConsoleFunction( strupr, const char*, ( const char* str ),,
    "@see strlwr\n"
    "@ingroup Strings" )
 {
-   char *ret = Con::getReturnBuffer(dStrlen(str) + 1);
-   dStrcpy(ret, str);
+   dsize_t retLen = dStrlen(str) + 1;
+   char *ret = Con::getReturnBuffer(retLen);
+   dStrcpy(ret, str, retLen);
    return dStrupr(ret);
 }
 
@@ -663,7 +666,8 @@ DefineConsoleFunction( strreplace, const char*, ( const char* source, const char
          count++;
       }
    }
-   char *ret = Con::getReturnBuffer(dStrlen(source) + 1 + (toLen - fromLen) * count);
+   S32 retLen = dStrlen(source) + 1 + (toLen - fromLen) * count;
+   char *ret = Con::getReturnBuffer(retLen);
    U32 scanp = 0;
    U32 dstp = 0;
    for(;;)
@@ -671,13 +675,13 @@ DefineConsoleFunction( strreplace, const char*, ( const char* source, const char
       const char *subScan = dStrstr(source + scanp, from);
       if(!subScan)
       {
-         dStrcpy(ret + dstp, source + scanp);
+         dStrcpy(ret + dstp, source + scanp, retLen - dstp);
          return ret;
       }
       U32 len = subScan - (source + scanp);
-      dStrncpy(ret + dstp, source + scanp, len);
+      dStrncpy(ret + dstp, source + scanp, getMin(len, retLen - dstp));
       dstp += len;
-      dStrcpy(ret + dstp, to);
+      dStrcpy(ret + dstp, to, retLen - dstp);
       dstp += toLen;
       scanp += len + fromLen;
    }
@@ -901,8 +905,8 @@ DefineConsoleFunction( startsWith, bool, ( const char* str, const char* prefix,
    char* targetBuf = new char[ targetLen + 1 ];
 
    // copy src and target into buffers
-   dStrcpy( srcBuf, str );
-   dStrcpy( targetBuf, prefix );
+   dStrcpy( srcBuf, str, srcLen + 1 );
+   dStrcpy( targetBuf, prefix, targetLen + 1 );
 
    // reassign src/target pointers to lowercase versions
    str = dStrlwr( srcBuf );
@@ -952,8 +956,8 @@ DefineConsoleFunction( endsWith, bool, ( const char* str, const char* suffix, bo
    char* targetBuf = new char[ targetLen + 1 ];
 
    // copy src and target into buffers
-   dStrcpy( srcBuf, str );
-   dStrcpy( targetBuf, suffix );
+   dStrcpy( srcBuf, str, srcLen + 1 );
+   dStrcpy( targetBuf, suffix, targetLen + 1 );
 
    // reassign src/target pointers to lowercase versions
    str = dStrlwr( srcBuf );
@@ -1824,8 +1828,9 @@ DefineEngineFunction( detag, const char*, ( const char* str ),,
       if( word == NULL )
          return "";
          
-      char* ret = Con::getReturnBuffer( dStrlen( word + 1 ) + 1 );
-      dStrcpy( ret, word + 1 );
+      dsize_t retLen = dStrlen(word + 1) + 1;
+      char* ret = Con::getReturnBuffer(retLen);
+      dStrcpy( ret, word + 1, retLen );
       return ret;
    }
    else
@@ -1889,7 +1894,7 @@ ConsoleFunction( echo, void, 2, 0, "( string message... ) "
    char *ret = Con::getReturnBuffer(len + 1);
    ret[0] = 0;
    for(i = 1; i < argc; i++)
-      dStrcat(ret, argv[i]);
+      dStrcat(ret, argv[i], len + 1);
 
    Con::printf("%s", ret);
    ret[0] = 0;
@@ -1913,7 +1918,7 @@ ConsoleFunction( warn, void, 2, 0, "( string message... ) "
    char *ret = Con::getReturnBuffer(len + 1);
    ret[0] = 0;
    for(i = 1; i < argc; i++)
-      dStrcat(ret, argv[i]);
+      dStrcat(ret, argv[i], len + 1);
 
    Con::warnf(ConsoleLogEntry::General, "%s", ret);
    ret[0] = 0;
@@ -1937,7 +1942,7 @@ ConsoleFunction( error, void, 2, 0, "( string message... ) "
    char *ret = Con::getReturnBuffer(len + 1);
    ret[0] = 0;
    for(i = 1; i < argc; i++)
-      dStrcat(ret, argv[i]);
+      dStrcat(ret, argv[i], len + 1);
 
    Con::errorf(ConsoleLogEntry::General, "%s", ret);
    ret[0] = 0;

+ 14 - 14
Engine/source/console/consoleInternal.cpp

@@ -125,7 +125,7 @@ StringValue & StringValue::operator=(const char *string)
    {
       S32 len = dStrlen(string);
       if (len < size)
-         dStrcpy(val, string);
+         dStrcpy(val, string, size);
       else
       {
          size = len;
@@ -569,7 +569,7 @@ void ConsoleValue::setStringValue(const char * value)
       type = TypeInternalString;
 
       bufferLen = newLen;
-      dStrcpy(sval, value);
+      dStrcpy(sval, value, newLen);
    }
    else
       Con::setData(type, dataPtr, 0, 1, &value, enumTable);
@@ -702,7 +702,7 @@ Dictionary::Entry* Dictionary::addVariable(const char *name,
    if (name[0] != '$')
    {
       scratchBuffer[0] = '$';
-      dStrcpy(scratchBuffer + 1, name);
+      dStrcpy(scratchBuffer + 1, name, 1023);
       name = scratchBuffer;
    }
 
@@ -900,21 +900,21 @@ DefineEngineFunction(backtrace, void, (), ,
    buf[0] = 0;
    for (U32 i = 0; i < gEvalState.getStackDepth(); i++)
    {
-      dStrcat(buf, "->");
+      dStrcat(buf, "->", totalSize);
 
       if (gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage)
       {
-         dStrcat(buf, "[");
-         dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage);
-         dStrcat(buf, "]");
+         dStrcat(buf, "[", totalSize);
+         dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage, totalSize);
+         dStrcat(buf, "]", totalSize);
       }
       if (gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mName)
       {
-         dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mName);
-         dStrcat(buf, "::");
+         dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mName, totalSize);
+         dStrcat(buf, "::", totalSize);
       }
       if (gEvalState.stack[i]->scopeName)
-         dStrcat(buf, gEvalState.stack[i]->scopeName);
+         dStrcat(buf, gEvalState.stack[i]->scopeName, totalSize);
    }
 
    Con::printf("BackTrace: %s", buf);
@@ -1360,9 +1360,9 @@ void Namespace::addScriptCallback(const char *funcName, const char *usage, Conso
    static U32 uid = 0;
    char buffer[1024];
    char lilBuffer[32];
-   dStrcpy(buffer, funcName);
+   dStrcpy(buffer, funcName, 1024);
    dSprintf(lilBuffer, 32, "_%d_cb", uid++);
-   dStrcat(buffer, lilBuffer);
+   dStrcat(buffer, lilBuffer, 1024);
 
    Entry *ent = createLocalEntry(StringTable->insert(buffer));
    trashCache();
@@ -1381,9 +1381,9 @@ void Namespace::markGroup(const char* name, const char* usage)
    static U32 uid = 0;
    char buffer[1024];
    char lilBuffer[32];
-   dStrcpy(buffer, name);
+   dStrcpy(buffer, name, 1024);
    dSprintf(lilBuffer, 32, "_%d", uid++);
-   dStrcat(buffer, lilBuffer);
+   dStrcat(buffer, lilBuffer, 1024);
 
    Entry *ent = createLocalEntry(StringTable->insert(buffer));
    trashCache();

+ 8 - 8
Engine/source/console/consoleObject.cpp

@@ -356,7 +356,7 @@ void ConsoleObject::addGroup(const char* in_pGroupname, const char* in_pGroupDoc
    char* pFieldNameBuf = suppressSpaces(in_pGroupname);
 
    // Append group type to fieldname.
-   dStrcat(pFieldNameBuf, "_begingroup");
+   dStrcat(pFieldNameBuf, "_begingroup", 1024);
 
    // Create Field.
    AbstractClassRep::Field f;
@@ -385,7 +385,7 @@ void ConsoleObject::endGroup(const char*  in_pGroupname)
    char* pFieldNameBuf = suppressSpaces(in_pGroupname);
 
    // Append group type to fieldname.
-   dStrcat(pFieldNameBuf, "_endgroup");
+   dStrcat(pFieldNameBuf, "_endgroup", 1024);
 
    // Create Field.
    AbstractClassRep::Field f;
@@ -407,7 +407,7 @@ void ConsoleObject::endGroup(const char*  in_pGroupname)
 void ConsoleObject::addArray( const char *arrayName, S32 count )
 {
    char *nameBuff = suppressSpaces(arrayName);
-   dStrcat(nameBuff, "_beginarray");
+   dStrcat(nameBuff, "_beginarray", 1024);
 
    // Create Field.
    AbstractClassRep::Field f;
@@ -430,7 +430,7 @@ void ConsoleObject::addArray( const char *arrayName, S32 count )
 void ConsoleObject::endArray( const char *arrayName )
 {
    char *nameBuff = suppressSpaces(arrayName);
-   dStrcat(nameBuff, "_endarray");
+   dStrcat(nameBuff, "_endarray", 1024);
 
    // Create Field.
    AbstractClassRep::Field f;
@@ -773,11 +773,11 @@ static const char* returnClassList( Vector< AbstractClassRep* >& classes, U32 bu
    dQsort( classes.address(), classes.size(), sizeof( AbstractClassRep* ), ACRCompare );
 
    char* ret = Con::getReturnBuffer( bufSize );
-   dStrcpy( ret, classes[ 0 ]->getClassName() );
+   dStrcpy( ret, classes[ 0 ]->getClassName(), bufSize );
    for( U32 i = 1; i < classes.size(); i ++ )
    {
-      dStrcat( ret, "\t" );
-      dStrcat( ret, classes[ i ]->getClassName() );
+      dStrcat( ret, "\t", bufSize );
+      dStrcat( ret, classes[ i ]->getClassName(), bufSize );
    }
    
    return ret;
@@ -888,7 +888,7 @@ DefineEngineFunction( enumerateConsoleClassesByCategory, const char*, ( String c
           && ( repCategory[ categoryLength ] == ' ' || repCategory[ categoryLength ] == '\0' ) )
       {
          classes.push_back( rep );
-         bufSize += dStrlen( rep->getClassName() + 1 );
+         bufSize += dStrlen( rep->getClassName() ) + 1;
       }
    }
 

+ 2 - 2
Engine/source/console/consoleXMLExport.cpp

@@ -319,8 +319,8 @@ DefineConsoleFunction( consoleExportXML, const char*, (), ,"Exports console defi
    Con::XMLExport xmlExport;
    String xml;
    xmlExport.exportXML(xml);
-   char* ret = Con::getReturnBuffer(xml.length() + 1);
-   dStrcpy(ret, xml.c_str());
+   char* ret = Con::getReturnBuffer(xml.size());
+   dStrcpy(ret, xml.c_str(), xml.size());
    return ret;
 }
 

+ 3 - 3
Engine/source/console/fieldBrushObject.cpp

@@ -273,9 +273,9 @@ DefineConsoleMethod(FieldBrushObject, queryFields, const char*, (const char* sim
     for ( U32 groupIndex = 0; groupIndex < groupCount; ++groupIndex )
     {
         // Copy string element.
-        dStrcpy( tempBuf, StringUnit::getUnit( groupList, groupIndex, " \t\n" ) );
+        dStrcpy( tempBuf, StringUnit::getUnit( groupList, groupIndex, " \t\n" ), 256 );
         // Append internal name.
-        dStrcat( tempBuf, "_begingroup" );
+        dStrcat( tempBuf, "_begingroup", 256 );
         // Store Group.
         groups.push_back( StringTable->insert( tempBuf ) );
     }
@@ -416,7 +416,7 @@ void FieldBrushObject::copyFields( SimObject* pSimObject, const char* fieldList
         for ( U32 fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex )
         {
             // Copy string element.
-            dStrcpy( tempBuf, StringUnit::getUnit( fieldList, fieldIndex, " \t\n" ) );
+            dStrcpy( tempBuf, StringUnit::getUnit( fieldList, fieldIndex, " \t\n" ), bufferSizes );
 
             // Store field.
             fields.push_back( StringTable->insert( tempBuf ) );

+ 12 - 10
Engine/source/console/fileSystemFunctions.cpp

@@ -495,7 +495,7 @@ DefineEngineFunction(getDirectoryList, String, ( const char* path, S32 depth ),
    // Copy the directory names to the buffer.
    for (S32 i = 0; i < directories.size(); i++)
    {
-      dStrcpy(p, directories[i]);
+      dStrcpy(p, directories[i], length - (p - buffer));
       p += dStrlen(directories[i]);
       // Tab separated.
       p[0] = '\t';
@@ -537,7 +537,7 @@ DefineEngineFunction( fileModifiedTime, String, ( const char* fileName ),,
    String fileStr = Platform::localTimeToString( lt );
    
    char *buffer = Con::getReturnBuffer( fileStr.size() );
-   dStrcpy( buffer, fileStr );   
+   dStrcpy( buffer, fileStr, fileStr.size() );
    
    return buffer;
 }
@@ -560,7 +560,7 @@ DefineEngineFunction( fileCreatedTime, String, ( const char* fileName ),,
    String fileStr = Platform::localTimeToString( lt );
 
    char *buffer = Con::getReturnBuffer( fileStr.size() );
-   dStrcpy( buffer, fileStr );  
+   dStrcpy( buffer, fileStr, fileStr.size() );
 
    return buffer;
 }
@@ -609,7 +609,7 @@ DefineEngineFunction(fileBase, String, ( const char* fileName ),,
    S32 pathLen = dStrlen( fileName );
    FrameTemp<char> szPathCopy( pathLen + 1);
 
-   dStrcpy( szPathCopy, fileName );
+   dStrcpy( szPathCopy, fileName, pathLen + 1 );
    forwardslash( szPathCopy );
 
    const char *path = dStrrchr(szPathCopy, '/');
@@ -617,8 +617,9 @@ DefineEngineFunction(fileBase, String, ( const char* fileName ),,
       path = szPathCopy;
    else
       path++;
-   char *ret = Con::getReturnBuffer(dStrlen(path) + 1);
-   dStrcpy(ret, path);
+   dsize_t retLen = dStrlen(path) + 1;
+   char *ret = Con::getReturnBuffer(retLen);
+   dStrcpy(ret, path, retLen);
    char *ext = dStrrchr(ret, '.');
    if(ext)
       *ext = 0;
@@ -635,7 +636,7 @@ DefineEngineFunction(fileName, String, ( const char* fileName ),,
    S32 pathLen = dStrlen( fileName );
    FrameTemp<char> szPathCopy( pathLen + 1);
 
-   dStrcpy( szPathCopy, fileName );
+   dStrcpy( szPathCopy, fileName, pathLen + 1 );
    forwardslash( szPathCopy );
 
    const char *name = dStrrchr(szPathCopy, '/');
@@ -643,8 +644,9 @@ DefineEngineFunction(fileName, String, ( const char* fileName ),,
       name = szPathCopy;
    else
       name++;
-   char *ret = Con::getReturnBuffer(dStrlen(name));
-   dStrcpy(ret, name);
+   dsize_t retLen = dStrlen(name) + 1;
+   char *ret = Con::getReturnBuffer(retLen);
+   dStrcpy(ret, name, retLen);
    return ret;
 }
 
@@ -658,7 +660,7 @@ DefineEngineFunction(filePath, String, ( const char* fileName ),,
    S32 pathLen = dStrlen( fileName );
    FrameTemp<char> szPathCopy( pathLen + 1);
 
-   dStrcpy( szPathCopy, fileName );
+   dStrcpy( szPathCopy, fileName, pathLen + 1 );
    forwardslash( szPathCopy );
 
    const char *path = dStrrchr(szPathCopy, '/');

+ 5 - 5
Engine/source/console/persistenceManager.cpp

@@ -950,7 +950,7 @@ void PersistenceManager::updateToken( const U32 lineNumber, const U32 linePositi
    char* postString = ( char* ) dMalloc( postStringLen + 1 );
    if( needQuotes )
       postString[ 0 ] = '"';
-   dStrcpy( &postString[ needQuotes ? 1 : 0 ], postStringSrc );
+   dStrcpy( &postString[ needQuotes ? 1 : 0 ], postStringSrc, postStringLen + (needQuotes ? 0 : 1) );
    postString[ postStringLen ] = 0;
 
    // Calculate the length of our new line
@@ -967,10 +967,10 @@ void PersistenceManager::updateToken( const U32 lineNumber, const U32 linePositi
 
    // Build the new line with the
    // preString + newValue + postString
-   dStrcat(newLine, preString);
+   dStrcat(newLine, preString, newLineLen + 1);
    if ( newValue )
-      dStrcat(newLine, newValue);
-   dStrcat(newLine, postString);
+      dStrcat(newLine, newValue, newLineLen + 1);
+   dStrcat(newLine, postString, newLineLen + 1);
 
    // Clear our existing line
    if (mLineBuffer[lineNumber])
@@ -1243,7 +1243,7 @@ PersistenceManager::ParsedObject* PersistenceManager::writeNewObject(SimObject*
    char* indent = getObjectIndent(parentObject);
 
    if (parentObject)
-      dStrcat(indent, "   \0");
+      dStrcat(indent, "   \0", 2048);
 
    // Write out the beginning of the object declaration
    const char* dclToken = "new";

+ 5 - 5
Engine/source/console/scriptFilename.cpp

@@ -189,7 +189,7 @@ bool expandToolScriptFilename(char *filename, U32 size, const char *src)
          // Relative to script directory
          if(cbFullPath)
          {
-            dStrcpy(varBuf, cbFullPath);
+            dStrcpy(varBuf, cbFullPath, 1024);
             slash = dStrrchr(varBuf, '/');
             if(slash) *slash = 0;
 
@@ -219,7 +219,7 @@ bool expandOldScriptFilename(char *filename, U32 size, const char *src)
    const StringTableEntry cbName = CodeBlock::getCurrentCodeBlockName();
    if (!cbName)
    {
-      dStrcpy(filename, src);
+      dStrcpy(filename, src, size);
       return true;
    }
 
@@ -244,7 +244,7 @@ bool expandOldScriptFilename(char *filename, U32 size, const char *src)
          *filename = 0;
          return false;
       }
-      dStrcpy(filename, src);
+      dStrcpy(filename, src, size);
       return true;
    }
 
@@ -264,7 +264,7 @@ bool expandOldScriptFilename(char *filename, U32 size, const char *src)
    }
 
    dStrncpy(filename, cbName, length);
-   dStrcpy(filename+length, src+1);
+   dStrcpy(filename+length, src+1, size - length);
    return true;
 }
 
@@ -325,7 +325,7 @@ bool collapseScriptFilename(char *filename, U32 size, const char *src)
       *filename = 0;
       if(*test[i].replace)
          dSprintf(filename, size, "%s/", test[i].replace);
-      dStrcat(filename, rel);
+      dStrcat(filename, rel, size);
       return true;
    }
 

+ 2 - 2
Engine/source/console/sim.cpp

@@ -216,7 +216,7 @@ DefineConsoleFunction( getUniqueName, const char*, (const char * baseName), ,
       return NULL;
 
    char *buffer = Con::getReturnBuffer( outName.size() );
-   dStrcpy( buffer, outName );
+   dStrcpy( buffer, outName, outName.size() );
 
    return buffer;
 }
@@ -241,7 +241,7 @@ DefineConsoleFunction( getUniqueInternalName, const char*, (const char * baseNam
       return NULL;
 
    char *buffer = Con::getReturnBuffer( outName.size() );
-   dStrcpy( buffer, outName );
+   dStrcpy( buffer, outName, outName.size() );
 
    return buffer;
 }

+ 2 - 2
Engine/source/console/simDatablock.cpp

@@ -198,10 +198,10 @@ void SimDataBlock::performSubstitutions(SimDataBlock* dblock, const SimObject* o
    }
 
    char obj_str[32];
-   dStrcpy(obj_str, Con::getIntArg(obj->getId()));
+   dStrcpy(obj_str, Con::getIntArg(obj->getId()), 32);
 
    char index_str[32];
-   dStrcpy(index_str, Con::getIntArg(index));
+   dStrcpy(index_str, Con::getIntArg(index), 32);
 
    for (S32 i = 0; i < substitutions.size(); i++)
    {

+ 1 - 1
Engine/source/console/simFieldDictionary.cpp

@@ -281,7 +281,7 @@ void SimFieldDictionary::writeFields(SimObject *obj, Stream &stream, U32 tabStop
       dSprintf(expandedBuffer, nBufferSize, "%s%s%s = \"", typeName, *typeName ? " " : "", (*itr)->slotName);
       if ((*itr)->value)
          expandEscape((char*)expandedBuffer + dStrlen(expandedBuffer), (*itr)->value);
-      dStrcat(expandedBuffer, "\";\r\n");
+      dStrcat(expandedBuffer, "\";\r\n", nBufferSize);
 
       stream.write(dStrlen(expandedBuffer), expandedBuffer);
    }

+ 14 - 14
Engine/source/console/simObject.cpp

@@ -320,7 +320,7 @@ void SimObject::writeFields(Stream &stream, U32 tabStop)
 
          U32 nBufferSize = dStrlen( val ) + 1;
          FrameTemp<char> valCopy( nBufferSize );
-         dStrcpy( (char *)valCopy, val );
+         dStrcpy( (char *)valCopy, val, nBufferSize );
 
          if (!writeField(f->pFieldname, valCopy))
             continue;
@@ -347,7 +347,7 @@ void SimObject::writeFields(Stream &stream, U32 tabStop)
          }
 
          expandEscape((char*)expandedBuffer + dStrlen(expandedBuffer), val);
-         dStrcat(expandedBuffer, "\";\r\n");
+         dStrcat(expandedBuffer, "\";\r\n", expandedBufferSize);
 
          stream.writeTabs(tabStop);
          stream.write(dStrlen(expandedBuffer),expandedBuffer);
@@ -402,12 +402,12 @@ bool SimObject::save(const char *pcFileName, bool bOnlySelected, const char *pre
    char docRoot[256];
    char modRoot[256];
 
-   dStrcpy(docRoot, pcFileName);
+   dStrcpy(docRoot, pcFileName, 256);
    char *p = dStrrchr(docRoot, '/');
    if (p) *++p = '\0';
    else  docRoot[0] = '\0';
 
-   dStrcpy(modRoot, pcFileName);
+   dStrcpy(modRoot, pcFileName, 256);
    p = dStrchr(modRoot, '/');
    if (p) *++p = '\0';
    else  modRoot[0] = '\0';
@@ -1028,8 +1028,8 @@ void SimObject::setDataField(StringTableEntry slotName, const char *array, const
       else
       {
          char buf[256];
-         dStrcpy(buf, slotName);
-         dStrcat(buf, array);
+         dStrcpy(buf, slotName, 256);
+         dStrcat(buf, array, 256);
          StringTableEntry permanentSlotName = StringTable->insert(buf);
          mFieldDictionary->setFieldValue(permanentSlotName, value);
          onDynamicModified( permanentSlotName, value );
@@ -1069,8 +1069,8 @@ const char *SimObject::getDataField(StringTableEntry slotName, const char *array
       else
       {
          static char buf[256];
-         dStrcpy(buf, slotName);
-         dStrcat(buf, array);
+         dStrcpy(buf, slotName, 256);
+         dStrcat(buf, array, 256);
          if (const char* val = mFieldDictionary->getFieldValue(StringTable->insert(buf)))
             return val;
       }
@@ -1310,8 +1310,8 @@ U32 SimObject::getDataFieldType( StringTableEntry slotName, const char* array )
    else
    {
       static char buf[256];
-      dStrcpy( buf, slotName );
-      dStrcat( buf, array );
+      dStrcpy( buf, slotName, 256 );
+      dStrcat( buf, array, 256 );
 
       return mFieldDictionary->getFieldType( StringTable->insert( buf ) );
    }
@@ -1333,8 +1333,8 @@ void SimObject::setDataFieldType(const U32 fieldTypeId, StringTableEntry slotNam
    else
    {
       static char buf[256];
-      dStrcpy( buf, slotName );
-      dStrcat( buf, array );
+      dStrcpy( buf, slotName, 256 );
+      dStrcat( buf, array, 256 );
 
       mFieldDictionary->setFieldType( StringTable->insert( buf ), fieldTypeId );
       onDynamicModified( slotName, mFieldDictionary->getFieldValue(slotName) );
@@ -1354,8 +1354,8 @@ void SimObject::setDataFieldType(const char *typeName, StringTableEntry slotName
    else
    {
       static char buf[256];
-      dStrcpy( buf, slotName );
-      dStrcat( buf, array );
+      dStrcpy( buf, slotName, 256 );
+      dStrcat( buf, array, 256 );
       StringTableEntry permanentSlotName = StringTable->insert(buf);
 
       mFieldDictionary->setFieldType( permanentSlotName, typeName );

+ 3 - 2
Engine/source/console/simObjectMemento.cpp

@@ -134,10 +134,11 @@ SimObject *SimObjectMemento::restore() const
             return NULL;
          U32 numCharsToLeftParen = pLeftParen - mState;
 
-         tempBuffer = ( char* ) dMalloc( dStrlen( mState ) + uniqueNameLen + 1 );
+         dsize_t tempBufferLen = dStrlen(mState) + uniqueNameLen + 1;
+         tempBuffer = ( char* ) dMalloc( tempBufferLen );
          dMemcpy( tempBuffer, mState, numCharsToLeftParen );
          dMemcpy( &tempBuffer[ numCharsToLeftParen ], uniqueName, uniqueNameLen );
-         dStrcpy( &tempBuffer[ numCharsToLeftParen + uniqueNameLen ], &mState[ numCharsToLeftParen ] );
+         dStrcpy( &tempBuffer[ numCharsToLeftParen + uniqueNameLen ], &mState[ numCharsToLeftParen ], tempBufferLen - numCharsToLeftParen - uniqueNameLen );
       }
 
       Con::evaluate( tempBuffer );

+ 1 - 1
Engine/source/console/stringStack.h

@@ -176,7 +176,7 @@ struct StringStack
       mLen = dStrlen(s);
 
       validateBufferSize(mStart + mLen + 2);
-      dStrcpy(mBuffer + mStart, s);
+      dStrcpy(mBuffer + mStart, s, mBufferSize - mStart);
    }
 
    /// Get the top of the stack, as a StringTableEntry.

+ 5 - 5
Engine/source/console/telnetDebugger.cpp

@@ -470,19 +470,19 @@ void TelnetDebugger::sendBreak()
       if ( ns ) {
 
          if ( ns->mParent && ns->mParent->mPackage && ns->mParent->mPackage[0] ) {
-            dStrcat( scope, ns->mParent->mPackage );
-            dStrcat( scope, "::" );
+            dStrcat( scope, ns->mParent->mPackage, MaxCommandSize );
+            dStrcat( scope, "::", MaxCommandSize );
          }
          if ( ns->mName && ns->mName[0] ) {
-            dStrcat( scope, ns->mName );
-            dStrcat( scope, "::" );
+            dStrcat( scope, ns->mName, MaxCommandSize );
+            dStrcat( scope, "::", MaxCommandSize );
          }
       }
 
       const char *function = gEvalState.stack[i]->scopeName;
       if ((!function) || (!function[0]))
          function = "<none>";
-      dStrcat( scope, function );
+      dStrcat( scope, function, MaxCommandSize );
 
       U32 line=0, inst;
       U32 ip = gEvalState.stack[i]->ip;

+ 1 - 1
Engine/source/core/frameAllocator.h

@@ -185,7 +185,7 @@ public:
 /// the FrameAllocator. For example:
 /// @code
 /// FrameTemp<char> tempStr(32); // NOTE! This parameter is NOT THE SIZE IN BYTES. See constructor docs.
-/// dStrcat( tempStr, SomeOtherString );
+/// dStrcat( tempStr, SomeOtherString, 32 * sizeof(char) );
 /// tempStr[2] = 'l';
 /// Con::printf( tempStr );
 /// Con::printf( "Foo: %s", ~tempStr );

+ 2 - 2
Engine/source/core/stream/bitStream.cpp

@@ -668,13 +668,13 @@ void BitStream::readString(char buf[256])
       {
          S32 offset = readInt(8);
          HuffmanProcessor::g_huffProcessor.readHuffBuffer(this, stringBuffer + offset);
-         dStrcpy(buf, stringBuffer);
+         dStrcpy(buf, stringBuffer, 256);
          return;
       }
    }
    HuffmanProcessor::g_huffProcessor.readHuffBuffer(this, buf);
    if(stringBuffer)
-      dStrcpy(stringBuffer, buf);
+      dStrcpy(stringBuffer, buf, 256);
 }
 
 void BitStream::writeString(const char *string, S32 maxLen)

+ 3 - 2
Engine/source/core/stringTable.cpp

@@ -142,10 +142,11 @@ StringTableEntry _StringTable::insert(const char* _val, const bool caseSens)
    }
    char *ret = 0;
    if(!*walk) {
+      dsize_t valLen = dStrlen(val) + 1;
       *walk = (Node *) mempool.alloc(sizeof(Node));
       (*walk)->next = 0;
-      (*walk)->val = (char *) mempool.alloc(dStrlen(val) + 1);
-      dStrcpy((*walk)->val, val);
+      (*walk)->val = (char *) mempool.alloc(valLen);
+      dStrcpy((*walk)->val, val, valLen);
       ret = (*walk)->val;
       itemCount ++;
    }

+ 5 - 4
Engine/source/core/strings/findMatch.cpp

@@ -71,8 +71,9 @@ void FindMatch::setExpression( const char *_expression )
 {
    delete [] expression;
 
-   expression = new char[dStrlen(_expression) + 1];
-   dStrcpy(expression, _expression);
+   dsize_t expressionLen = dStrlen(_expression) + 1;
+   expression = new char[expressionLen];
+   dStrcpy(expression, _expression, expressionLen);
    dStrupr(expression);
 }
 
@@ -82,7 +83,7 @@ bool FindMatch::findMatch( const char *str, bool caseSensitive )
       return false;
 
    char nstr[512];
-   dStrcpy( nstr,str );
+   dStrcpy( nstr,str,512 );
    dStrupr(nstr);
    if ( isMatch( expression, nstr, caseSensitive ) )
    {
@@ -143,7 +144,7 @@ bool FindMatch::isMatchMultipleExprs( const char *exps, const char *str, bool ca
    S32 len = dStrlen(exps);
 
    char *e = new char[len+1];
-   dStrcpy(e,exps);
+   dStrcpy(e,exps,len+1);
 
    // [tom, 12/18/2006] This no longer supports space separated expressions as
    // they don't work when the paths have spaces in.

+ 64 - 2
Engine/source/core/strings/stringFunctions.cpp

@@ -215,8 +215,9 @@ S32 dStrnatcasecmp(const nat_char* a, const nat_char* b) {
 
 char *dStrdup_r(const char *src, const char *fileName, dsize_t lineNumber)
 {
-   char *buffer = (char *) dMalloc_r(dStrlen(src) + 1, fileName, lineNumber);
-   dStrcpy(buffer, src);
+   dsize_t bufferLen = dStrlen(src) + 1;
+   char *buffer = (char *) dMalloc_r(bufferLen, fileName, lineNumber);
+   dStrcpy(buffer, src, bufferLen);
    return buffer;
 }
 
@@ -381,6 +382,67 @@ char* dStrlwr(char *str)
 #endif
 }
 
+//------------------------------------------------------------------------------
+
+S32 dStrlcat(char *dst, const char *src, dsize_t dstSize)
+{
+   //TODO: Do other platforms support strlcat in their libc
+#ifdef TORQUE_OS_MAC
+   S32 len = strlcat(dst, src, dstSize);
+
+   AssertWarn(len < dstSize, "Buffer too small in call to dStrlcat!");
+
+   return len;
+#else //TORQUE_OS_MAC
+   S32 dstLen = dStrlen(dst);
+   S32 srcLen = dStrlen(src);
+   S32 copyLen = srcLen;
+
+   //Check for buffer overflow and don't allow it. Warn on debug so we can fix it
+   AssertWarn(dstLen + copyLen < dstSize, "Buffer too small in call to dStrlcat!");
+   if (dstLen + copyLen + 1 > dstSize)
+   {
+      copyLen = dstSize - dstLen - 1;
+   }
+
+   //Copy src after dst and null terminate
+   memcpy(dst + dstLen, src, copyLen);
+   dst[dstLen + copyLen] = 0;
+
+   //Return the length of the string we would have generated
+   return dstLen + srcLen;
+#endif //TORQUE_OS_MAC
+}
+
+S32 dStrlcpy(char *dst, const char *src, dsize_t dstSize)
+{
+   //TODO: Do other platforms support strlcpy in their libc
+#ifdef TORQUE_OS_MAC
+   S32 len = strlcpy(dst, src, dstSize);
+
+   AssertWarn(len < dstSize, "Buffer too small in call to dStrlcpy!");
+
+   return len;
+#else //TORQUE_OS_MAC
+   S32 srcLen = dStrlen(src);
+   S32 copyLen = srcLen;
+
+   //Check for buffer overflow and don't allow it. Warn on debug so we can fix it
+   AssertWarn(copyLen < dstSize, "Buffer too small in call to dStrlcpy!");
+   if (srcLen + 1 > dstSize)
+   {
+      copyLen = dstSize - 1;
+   }
+
+   //Copy src and null terminate
+   memcpy(dst, src, copyLen);
+   dst[copyLen] = 0;
+
+   //Return the length of the string we would have generated
+   return srcLen;
+#endif //TORQUE_OS_MAC
+}
+
 //------------------------------------------------------------------------------
 // standard I/O functions
 

+ 35 - 2
Engine/source/core/strings/stringFunctions.h

@@ -32,6 +32,10 @@
 #include "platform/types.h"
 #endif
 
+#ifndef _PLATFORMASSERT_H_
+#include "platform/platformAssert.h"
+#endif
+
 #if defined(TORQUE_OS_WIN)
 // These standard functions are not defined on Win32 and other Microsoft platforms...
 #define strcasecmp   _stricmp
@@ -43,18 +47,37 @@
 
 #endif // defined(TORQUE_OS_WIN)
 
-
 //------------------------------------------------------------------------------
 // standard string functions [defined in platformString.cpp]
 
+// Buffer size bounds checking "safe" versions of strcat and strcpy. Ideally you
+// should use these and check if they return >= dstSize and throw an error if so.
+extern S32  dStrlcat(char *dst, const char *src, dsize_t dstSize);
+extern S32  dStrlcpy(char *dst, const char *src, dsize_t dstSize);
+
+#ifdef UNSAFE_STRING_FUNCTIONS
+/// @deprecated Use dStrcat(char *, const char *, dsize_t) instead
 inline char *dStrcat(char *dst, const char *src)
 {
+   AssertFatal(false, "dStrcat without length is deprecated");
    return strcat(dst,src);
 }   
+#endif
+
+/// Concatenate strings.
+/// @note The third parameter is the size of the destination buffer like strlcat
+///       instead of the number of characters to copy like strncat. This is done
+///       under the assumption that being easier to use will make this safer.
+///       If you want the original behavior use dStrncat.
+inline char *dStrcat(char *dst, const char *src, dsize_t dstSize)
+{
+   dStrlcat(dst, src, dstSize);
+   return dst;
+}
 
 inline char *dStrncat(char *dst, const char *src, dsize_t len)
 {
-   return strncat(dst,src,len);
+   return strncat(dst, src, len);
 }
 
 inline S32  dStrcmp(const char *str1, const char *str2)
@@ -82,9 +105,19 @@ inline S32  dStrnicmp(const char *str1, const char *str2, dsize_t len)
    return strncasecmp( str1, str2, len );
 }
 
+#ifdef UNSAFE_STRING_FUNCTIONS
+/// @deprecated Use strcpy(char *, const char *, dsize_t) instead
 inline char *dStrcpy(char *dst, const char *src)
 {
+   AssertFatal(false, "dStrcpy without length is deprecated");
    return strcpy(dst,src);
+}
+#endif
+
+inline char *dStrcpy(char *dst, const char *src, dsize_t dstSize)
+{
+   dStrlcpy(dst, src, dstSize);
+   return dst;
 }   
 
 inline char *dStrncpy(char *dst, const char *src, dsize_t len)

+ 3 - 3
Engine/source/core/strings/stringUnit.cpp

@@ -164,7 +164,7 @@ namespace StringUnit
 
       // replace this unit
       ret[sz] = '\0';
-      dStrcat(ret, replace);
+      dStrcat(ret, replace, 2048);
 
       // copy remaining chunks
       sz = dStrcspn(string, set);         // skip chunk we're replacing
@@ -172,7 +172,7 @@ namespace StringUnit
          return ret;
 
       string += sz;
-      dStrcat(ret, string);
+      dStrcat(ret, string, 2048);
       return ret;
    }
 
@@ -211,7 +211,7 @@ namespace StringUnit
       }
 
       string += sz + 1; // skip the extra field delimiter
-      dStrcat(ret, string);
+      dStrcat(ret, string, 2048);
       return ret;
    }
 }

+ 3 - 3
Engine/source/core/tokenizer.cpp

@@ -61,7 +61,7 @@ bool Tokenizer::openFile(const char* pFileName)
       delete pStream;
       return false;
    }
-   dStrcpy(mFileName, pFileName);
+   dStrcpy(mFileName, pFileName, 1024);
 
    mBufferSize = pStream->getStreamSize();
    mpBuffer    = new char[mBufferSize];
@@ -99,7 +99,7 @@ void Tokenizer::setBuffer(const char* buffer, U32 bufferSize)
 
    mBufferSize = bufferSize;
    mpBuffer    = new char[mBufferSize + 1];
-   dStrcpy(mpBuffer, buffer);
+   dStrcpy(mpBuffer, buffer, mBufferSize + 1);
 
    reset();
 
@@ -634,4 +634,4 @@ bool Tokenizer::endOfFile()
       return false;
    else
       return true;
-}
+}

+ 3 - 2
Engine/source/core/util/zip/centralDir.cpp

@@ -177,8 +177,9 @@ bool CentralDir::write(Stream *stream)
 void CentralDir::setFileComment(const char *comment)
 {
    SAFE_DELETE_ARRAY(mFileComment);
-   mFileComment = new char [dStrlen(comment)+1];
-   dStrcpy(mFileComment, comment);
+   dsize_t commentLen = dStrlen(comment) + 1;
+   mFileComment = new char [commentLen];
+   dStrcpy(mFileComment, comment, commentLen);
 }
 
 //-----------------------------------------------------------------------------

+ 2 - 2
Engine/source/core/util/zip/test/zipTestWrite.cpp

@@ -95,7 +95,7 @@ private:
       {
          // Find a unique filename
          U32 count = 1;
-         dStrcpy(fileBuf, filename);
+         dStrcpy(fileBuf, filename, bufSize);
          
          while(zip->findFileInfo(fileBuf))
          {
@@ -109,7 +109,7 @@ private:
          }
       }
       else if(fileBuf && bufSize > 0)
-         dStrcpy(fileBuf, filename);
+         dStrcpy(fileBuf, filename, bufSize);
 
       // Try and write to the file
       Stream * stream = zip->openFile(fileBuf ? fileBuf : filename, ZipArchive::Write);

+ 2 - 2
Engine/source/gfx/Null/gfxNullDevice.cpp

@@ -309,7 +309,7 @@ void GFXNullDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
    vm.resolution.set(800,600);
    toAdd->mAvailableModes.push_back(vm);
 
-   dStrcpy(toAdd->mName, "GFX Null Device");
+   dStrcpy(toAdd->mName, "GFX Null Device", GFXAdapter::MaxAdapterNameLen);
 
    adapterList.push_back(toAdd);
 }
@@ -342,4 +342,4 @@ public:
    }
 };
 
-static GFXNullRegisterDevice pNullRegisterDevice;
+static GFXNullRegisterDevice pNullRegisterDevice;

+ 4 - 3
Engine/source/gfx/gfxStructs.cpp

@@ -39,8 +39,9 @@ void GFXVideoMode::parseFromString( const char *str )
       return;
 
    // Copy the string, as dStrtok is destructive
-   char *tempBuf = new char[dStrlen( str ) + 1];
-   dStrcpy( tempBuf, str );
+   dsize_t tempBufLen = dStrlen(str) + 1;
+   char *tempBuf = new char[tempBufLen];
+   dStrcpy( tempBuf, str, tempBufLen );
 
 #define PARSE_ELEM(type, var, func, tokParam, sep) \
    if(const char *ptr = dStrtok( tokParam, sep)) \
@@ -76,4 +77,4 @@ void GFXShaderMacro::stringize( const Vector<GFXShaderMacro> &macros, String *ou
       }
       (*outString) += ";";
    }
-}
+}

+ 3 - 3
Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp

@@ -128,11 +128,11 @@ void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
 
    if (renderer)
    {
-      dStrcpy(toAdd->mName, renderer);
-      dStrncat(toAdd->mName, " OpenGL", GFXAdapter::MaxAdapterNameLen);
+      dStrcpy(toAdd->mName, renderer, GFXAdapter::MaxAdapterNameLen);
+      dStrcat(toAdd->mName, " OpenGL", GFXAdapter::MaxAdapterNameLen);
    }
    else
-      dStrcpy(toAdd->mName, "OpenGL");
+      dStrcpy(toAdd->mName, "OpenGL", GFXAdapter::MaxAdapterNameLen);
 
    toAdd->mType = OpenGL;
    toAdd->mShaderModel = 0.f;

+ 2 - 2
Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp

@@ -129,11 +129,11 @@ void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
 
    if (renderer)
    {
-      dStrcpy(toAdd->mName, renderer);
+      dStrcpy(toAdd->mName, renderer, GFXAdapter::MaxAdapterNameLen);
       dStrncat(toAdd->mName, " OpenGL", GFXAdapter::MaxAdapterNameLen);
    }
    else
-      dStrcpy(toAdd->mName, "OpenGL");
+      dStrcpy(toAdd->mName, "OpenGL", GFXAdapter::MaxAdapterNameLen);
 
    toAdd->mType = OpenGL;
    toAdd->mShaderModel = 0.f;

+ 1 - 1
Engine/source/gfx/screenshot.cpp

@@ -55,7 +55,7 @@ ScreenShot::ScreenShot()
 
 void ScreenShot::setPending( const char *filename, bool writeJPG, S32 tiles, F32 overlap )
 {
-   dStrcpy( mFilename, filename );
+   dStrcpy( mFilename, filename, 256 );
    mWriteJPG = writeJPG;
    mTiles = getMax( tiles, 1 );
    mPixelOverlap.set(getMin(overlap, 0.25f), getMin(overlap, 0.25f));      

+ 3 - 3
Engine/source/gui/containers/guiFormCtrl.cpp

@@ -218,9 +218,9 @@ bool GuiFormCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
       S32 strlen = dStrlen((const char*)mCaption);
       for(S32 i=strlen; i>=0; --i)
       {
-         dStrcpy(buf, "");
-         dStrncat(buf, (const char*)mCaption, i);
-         dStrcat(buf, "...");
+         dStrcpy(buf, "", i);
+         dStrcat(buf, (const char*)mCaption, i);
+         dStrcat(buf, "...", i);
 
          textWidth = mProfile->mFont->getStrWidth(buf);
 

+ 4 - 3
Engine/source/gui/controls/guiAnimBitmapCtrl.cpp

@@ -167,8 +167,9 @@ bool guiAnimBitmapCtrl::ptSetFrameRanges(void *object, const char *index, const
          pData->mCurFrameIndex = pData->mNumFrames;
       return true;
    }
-   char* tokCopy = new char[dStrlen(data) + 1];
-   dStrcpy(tokCopy, data);
+   dsize_t tokLen = dStrlen(data) + 1;
+   char* tokCopy = new char[tokLen];
+   dStrcpy(tokCopy, data, tokLen);
 
    char* currTok = dStrtok(tokCopy, " \t");
    while (currTok != NULL)
@@ -291,4 +292,4 @@ void guiAnimBitmapCtrl::onRender(Point2I offset, const RectI &updateRect)
    }
 
    renderChildControls(offset, updateRect);
-}
+}

+ 159 - 39
Engine/source/gui/controls/guiConsole.cpp

@@ -50,6 +50,12 @@ IMPLEMENT_CALLBACK( GuiConsole, onMessageSelected, void, ( ConsoleLogEntry::Leve
    "@param level Diagnostic level of the message.\n"
    "@param message Message text.\n" );
 
+IMPLEMENT_CALLBACK(GuiConsole, onNewMessage, void, (U32 errorCount, U32 warnCount, U32 normalCount), (errorCount, warnCount, normalCount),
+   "Called when a new message is logged.\n\n"
+   "@param errorCount The number of error messages logged.\n"
+   "@param warnCount The number of warning messages logged.\n"
+   "@param normalCount The number of normal messages logged.\n");
+
 
 //-----------------------------------------------------------------------------
 
@@ -58,6 +64,11 @@ GuiConsole::GuiConsole()
    setExtent(64, 64);
    mCellSize.set(1, 1);
    mSize.set(1, 0);
+
+   mDisplayErrors = true;
+   mDisplayWarnings = true;
+   mDisplayNormalMessages = true;
+   mFiltersDirty = true;
 }
 
 //-----------------------------------------------------------------------------
@@ -81,56 +92,98 @@ S32 GuiConsole::getMaxWidth(S32 startIndex, S32 endIndex)
    U32 size;
    ConsoleLogEntry *log;
 
-   Con::getLockLog(log, size);
-
-   if(startIndex < 0 || (U32)endIndex >= size || startIndex > endIndex)
+   if (startIndex < 0 || (U32)endIndex >= mFilteredLog.size() || startIndex > endIndex)
       return 0;
 
    S32 result = 0;
    for(S32 i = startIndex; i <= endIndex; i++)
-      result = getMax(result, (S32)(mFont->getStrWidth((const UTF8 *)log[i].mString)));
-   
-   Con::unlockLog();
+      result = getMax(result, (S32)(mFont->getStrWidth((const UTF8 *)mFilteredLog[i].mString)));
    
    return(result + 6);
 }
 
+void GuiConsole::refreshLogText()
+{
+   U32 size;
+   ConsoleLogEntry *log;
+
+   Con::getLockLog(log, size);
+
+   if (mFilteredLog.size() != size || mFiltersDirty)
+   {
+      mFilteredLog.clear();
+
+      U32 errorCount = 0;
+      U32 warnCount = 0;
+      U32 normalCount = 0;
+
+      //Filter the log if needed
+      for (U32 i = 0; i < size; ++i)
+      {
+         ConsoleLogEntry &entry = log[i];
+
+         if (entry.mLevel == ConsoleLogEntry::Error)
+         {
+            errorCount++;
+            if (mDisplayErrors)
+            {
+               mFilteredLog.push_back(entry);
+            }
+         }
+         else if (entry.mLevel == ConsoleLogEntry::Warning)
+         {
+            warnCount++;
+            if (mDisplayWarnings)
+            {
+               mFilteredLog.push_back(entry);
+            }
+         }
+         else if (entry.mLevel == ConsoleLogEntry::Normal)
+         {
+            normalCount++;
+            if (mDisplayNormalMessages)
+            {
+               mFilteredLog.push_back(entry);
+            }
+         }
+      }
+
+      onNewMessage_callback(errorCount, warnCount, normalCount);
+   }
+
+   Con::unlockLog();
+}
+
 //-----------------------------------------------------------------------------
 
 void GuiConsole::onPreRender()
 {
    //see if the size has changed
    U32 prevSize = getHeight() / mCellSize.y;
-   U32 size;
-   ConsoleLogEntry *log;
 
-   Con::getLockLog(log, size);
-   Con::unlockLog(); // we unlock immediately because we only use size here, not log.
+   refreshLogText();
    
-   if(size != prevSize)
-   {
-      //first, find out if the console was scrolled up
-      bool scrolled = false;
-      GuiScrollCtrl *parent = dynamic_cast<GuiScrollCtrl*>(getParent());
+   //first, find out if the console was scrolled up
+   bool scrolled = false;
+   GuiScrollCtrl *parent = dynamic_cast<GuiScrollCtrl*>(getParent());
 
-      if(parent)
-         scrolled = parent->isScrolledToBottom();
+   if(parent)
+      scrolled = parent->isScrolledToBottom();
 
-      //find the max cell width for the new entries
-      S32 newMax = getMaxWidth(prevSize, size - 1);
-      if(newMax > mCellSize.x)
-         mCellSize.set(newMax, mFont->getHeight());
+   //find the max cell width for the new entries
+   S32 newMax = getMaxWidth(prevSize, mFilteredLog.size() - 1);
+   if(newMax > mCellSize.x)
+      mCellSize.set(newMax, mFont->getHeight());
 
-      //set the array size
-      mSize.set(1, size);
+   //set the array size
+   mSize.set(1, mFilteredLog.size());
 
-      //resize the control
-      setExtent( Point2I(mCellSize.x, mCellSize.y * size));
+   //resize the control
+   setExtent(Point2I(mCellSize.x, mCellSize.y * mFilteredLog.size()));
 
-      //if the console was not scrolled, make the last entry visible
-      if (scrolled)
-         scrollCellVisible(Point2I(0,mSize.y - 1));
-   }
+   //if the console was not scrolled, make the last entry visible
+   if (scrolled)
+      scrollCellVisible(Point2I(0,mSize.y - 1));
 }
 
 //-----------------------------------------------------------------------------
@@ -139,10 +192,8 @@ void GuiConsole::onRenderCell(Point2I offset, Point2I cell, bool /*selected*/, b
 {
    U32 size;
    ConsoleLogEntry *log;
-
-   Con::getLockLog(log, size);
-
-   ConsoleLogEntry &entry = log[cell.y];
+   
+   ConsoleLogEntry &entry = mFilteredLog[cell.y];
    switch (entry.mLevel)
    {
       case ConsoleLogEntry::Normal:   GFX->getDrawUtil()->setBitmapModulation(mProfile->mFontColor); break;
@@ -151,8 +202,6 @@ void GuiConsole::onRenderCell(Point2I offset, Point2I cell, bool /*selected*/, b
       default: AssertFatal(false, "GuiConsole::onRenderCell - Unrecognized ConsoleLogEntry type, update this.");
    }
    GFX->getDrawUtil()->drawText(mFont, Point2I(offset.x + 3, offset.y), entry.mString, mProfile->mFontColors);
-   
-   Con::unlockLog();
 }
 
 //-----------------------------------------------------------------------------
@@ -164,10 +213,81 @@ void GuiConsole::onCellSelected( Point2I cell )
    U32 size;
    ConsoleLogEntry* log;
 
-   Con::getLockLog(log, size);
-
-   ConsoleLogEntry& entry = log[ cell.y ];
+   ConsoleLogEntry& entry = mFilteredLog[cell.y];
    onMessageSelected_callback( entry.mLevel, entry.mString );
+}
 
-   Con::unlockLog();
+void GuiConsole::setDisplayFilters(bool errors, bool warns, bool normal)
+{
+   mDisplayErrors = errors;
+   mDisplayWarnings = warns;
+   mDisplayNormalMessages = normal;
+   mFiltersDirty = true;
+
+   refreshLogText();
+
+   //find the max cell width for the new entries
+   S32 newMax = getMaxWidth(0, mFilteredLog.size() - 1);
+   mCellSize.set(newMax, mFont->getHeight());
+
+   //set the array size
+   mSize.set(1, mFilteredLog.size());
+
+   //resize the control
+   setExtent(Point2I(mCellSize.x, mCellSize.y * mFilteredLog.size()));
+
+   scrollCellVisible(Point2I(0, mSize.y - 1));
+
+   mFiltersDirty = false;
 }
+
+DefineEngineMethod(GuiConsole, setDisplayFilters, void, (bool errors, bool warns, bool normal), (true, true, true),
+   "Sets the current display filters for the console gui. Allows you to indicate if it should display errors, warns and/or normal messages.\n\n"
+   "@param errors If true, the console gui will display any error messages that were emitted.\n\n"
+   "@param warns If true, the console gui will display any warning messages that were emitted.\n\n"
+   "@param normal If true, the console gui will display any regular messages that were emitted.\n\n")
+{
+   object->setDisplayFilters(errors, warns, normal);
+}
+
+DefineEngineMethod(GuiConsole, getErrorFilter, bool, (), ,
+   "Returns if the error filter is on or not.")
+{
+   return object->getErrorFilter();
+}
+
+DefineEngineMethod(GuiConsole, getWarnFilter, bool, (), ,
+   "Returns if the warning filter is on or not.")
+{
+   return object->getWarnFilter();
+}
+
+DefineEngineMethod(GuiConsole, getNormalFilter, bool, (), ,
+   "Returns if the normal message filter is on or not.")
+{
+   return object->getNormalFilter();
+}
+
+DefineEngineMethod(GuiConsole, toggleErrorFilter, void, (), ,
+   "Toggles the error filter.")
+{
+   object->toggleErrorFilter();
+}
+
+DefineEngineMethod(GuiConsole, toggleWarnFilter, void, (), ,
+   "Toggles the warning filter.")
+{
+   object->toggleWarnFilter();
+}
+
+DefineEngineMethod(GuiConsole, toggleNormalFilter, void, (), ,
+   "Toggles the normal messages filter.")
+{
+   object->toggleNormalFilter();
+}
+
+DefineEngineMethod(GuiConsole, refresh, void, (), ,
+   "Refreshes the displayed messages.")
+{
+   object->refresh();
+}

+ 32 - 0
Engine/source/gui/controls/guiConsole.h

@@ -39,14 +39,22 @@ class GuiConsole : public GuiArrayCtrl
 
       Resource<GFont> mFont;
 
+      bool mDisplayErrors;
+      bool mDisplayWarnings;
+      bool mDisplayNormalMessages;
+      bool mFiltersDirty;
+
       S32 getMaxWidth(S32 startIndex, S32 endIndex);
 
+      Vector<ConsoleLogEntry> mFilteredLog;
+
    protected:
 
       /// @name Callbacks
       /// @{
 
       DECLARE_CALLBACK( void, onMessageSelected, ( ConsoleLogEntry::Level level, const char* message ) );
+      DECLARE_CALLBACK(void, onNewMessage, (U32 errorCount, U32 warnCount, U32 normalCount));
 
       /// @}
 
@@ -63,6 +71,30 @@ class GuiConsole : public GuiArrayCtrl
       virtual bool onWake();
       virtual void onPreRender();
       virtual void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
+
+      void setDisplayFilters(bool errors, bool warns, bool normal);
+      bool getErrorFilter() { return mDisplayErrors; }
+      bool getWarnFilter() { return mDisplayWarnings; }
+      bool getNormalFilter() { return mDisplayNormalMessages; }
+
+      void toggleErrorFilter()
+      {
+         setDisplayFilters(!mDisplayErrors, mDisplayWarnings, mDisplayNormalMessages);
+      }
+      void toggleWarnFilter()
+      {
+         setDisplayFilters(mDisplayErrors, !mDisplayWarnings, mDisplayNormalMessages);
+      }
+      void toggleNormalFilter()
+      {
+         setDisplayFilters(mDisplayErrors, mDisplayWarnings, !mDisplayNormalMessages);
+      }
+      void refresh()
+      {
+         setDisplayFilters(mDisplayErrors, mDisplayWarnings, mDisplayNormalMessages);
+      }
+
+      void refreshLogText();
 };
 
 #endif

+ 1 - 1
Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp

@@ -195,7 +195,7 @@ DefineEngineMethod( GuiDirectoryFileListCtrl, getSelectedFiles, const char*, (),
 
       dMemset( itemBuffer, 0, itemBufSize );
       dSprintf( itemBuffer, itemBufSize, " %s", itemText );
-      dStrcat( returnBuffer, itemBuffer );
+      dStrcat( returnBuffer, itemBuffer, itemBufSize );
    }
 
    return returnBuffer;

+ 1 - 1
Engine/source/gui/controls/guiFileTreeCtrl.cpp

@@ -276,7 +276,7 @@ void GuiFileTreeCtrl::recurseInsert( Item* parent, StringTableEntry path )
 
    char szPathCopy [ 1024 ];
    dMemset( szPathCopy, 0, 1024 );
-   dStrcpy( szPathCopy, path );
+   dStrcpy( szPathCopy, path, 1024 );
 
    // Jump over the first character if it's a root /
    char *curPos = szPathCopy;

+ 1 - 1
Engine/source/gui/controls/guiListBoxCtrl.cpp

@@ -458,7 +458,7 @@ DefineEngineMethod( GuiListBoxCtrl, getSelectedItems, const char*, (),,
    {
       UTF8 retFormat[12];
       dSprintf( retFormat, 12, "%d ", (*i) );
-      dStrcat( retBuffer, retFormat );
+      dStrcat( retBuffer, retFormat, 12 );
    }
 
    return retBuffer;

+ 5 - 4
Engine/source/gui/controls/guiPopUpCtrl.cpp

@@ -566,13 +566,14 @@ void GuiPopUpMenuCtrl::setBitmap( const char *name )
    {
       char buffer[1024];
       char *p;
-      dStrcpy(buffer, name);
+      dStrcpy(buffer, name, 1024);
       p = buffer + dStrlen(buffer);
+      S32 pLen = 1024 - dStrlen(buffer);
 
-      dStrcpy(p, "_n");
+      dStrcpy(p, "_n", pLen);
       mTextureNormal = GFXTexHandle( (StringTableEntry)buffer, &GFXDefaultGUIProfile, avar("%s() - mTextureNormal (line %d)", __FUNCTION__, __LINE__) );
 
-      dStrcpy(p, "_d");
+      dStrcpy(p, "_d", pLen);
       mTextureDepressed = GFXTexHandle( (StringTableEntry)buffer, &GFXDefaultGUIProfile, avar("%s() - mTextureDepressed (line %d)", __FUNCTION__, __LINE__) );
       if ( !mTextureDepressed )
          mTextureDepressed = mTextureNormal;
@@ -637,7 +638,7 @@ void GuiPopUpMenuCtrl::addEntry( const char *buf, S32 id, U32 scheme )
       mIdMax = id;
 
    Entry e;
-   dStrcpy( e.buf, buf );
+   dStrcpy( e.buf, buf, 256 );
    e.id = id;
    e.scheme = scheme;
 

+ 11 - 10
Engine/source/gui/controls/guiPopUpCtrlEx.cpp

@@ -390,7 +390,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, addScheme, void, (S32 id, ColorI fontCol
    U32 r, g, b;
    char buf[64];
 
-   dStrcpy( buf, argv[3] );
+   dStrcpy( buf, argv[3], 64 );
    char* temp = dStrtok( buf, " \0" );
    r = temp ? dAtoi( temp ) : 0;
    temp = dStrtok( NULL, " \0" );
@@ -399,7 +399,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, addScheme, void, (S32 id, ColorI fontCol
    b = temp ? dAtoi( temp ) : 0;
    fontColor.set( r, g, b );
 
-   dStrcpy( buf, argv[4] );
+   dStrcpy( buf, argv[4], 64 );
    temp = dStrtok( buf, " \0" );
    r = temp ? dAtoi( temp ) : 0;
    temp = dStrtok( NULL, " \0" );
@@ -408,7 +408,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, addScheme, void, (S32 id, ColorI fontCol
    b = temp ? dAtoi( temp ) : 0;
    fontColorHL.set( r, g, b );
 
-   dStrcpy( buf, argv[5] );
+   dStrcpy( buf, argv[5], 64 );
    temp = dStrtok( buf, " \0" );
    r = temp ? dAtoi( temp ) : 0;
    temp = dStrtok( NULL, " \0" );
@@ -426,7 +426,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, addScheme, void, (S32 id, ColorI fontCol
 //   U32 r, g, b;
 //   char buf[64];
 //
-//   dStrcpy( buf, argv[3] );
+//   dStrcpy( buf, argv[3], 64 );
 //   char* temp = dStrtok( buf, " \0" );
 //   r = temp ? dAtoi( temp ) : 0;
 //   temp = dStrtok( NULL, " \0" );
@@ -435,7 +435,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, addScheme, void, (S32 id, ColorI fontCol
 //   b = temp ? dAtoi( temp ) : 0;
 //   fontColor.set( r, g, b );
 //
-//   dStrcpy( buf, argv[4] );
+//   dStrcpy( buf, argv[4], 64 );
 //   temp = dStrtok( buf, " \0" );
 //   r = temp ? dAtoi( temp ) : 0;
 //   temp = dStrtok( NULL, " \0" );
@@ -444,7 +444,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, addScheme, void, (S32 id, ColorI fontCol
 //   b = temp ? dAtoi( temp ) : 0;
 //   fontColorHL.set( r, g, b );
 //
-//   dStrcpy( buf, argv[5] );
+//   dStrcpy( buf, argv[5], 64 );
 //   temp = dStrtok( buf, " \0" );
 //   r = temp ? dAtoi( temp ) : 0;
 //   temp = dStrtok( NULL, " \0" );
@@ -771,13 +771,14 @@ void GuiPopUpMenuCtrlEx::setBitmap(const char *name)
    {
       char buffer[1024];
       char *p;
-      dStrcpy(buffer, name);
+      dStrcpy(buffer, name, 1024);
       p = buffer + dStrlen(buffer);
+      S32 pLen = 1024 - dStrlen(buffer);
 
-      dStrcpy(p, "_n");
+      dStrcpy(p, "_n", pLen);
       mTextureNormal = GFXTexHandle( (StringTableEntry)buffer, &GFXDefaultGUIProfile, avar("%s() - mTextureNormal (line %d)", __FUNCTION__, __LINE__) );
 
-      dStrcpy(p, "_d");
+      dStrcpy(p, "_d", pLen);
       mTextureDepressed = GFXTexHandle( (StringTableEntry)buffer, &GFXDefaultGUIProfile, avar("%s() - mTextureDepressed (line %d)", __FUNCTION__, __LINE__) );
       if ( !mTextureDepressed )
          mTextureDepressed = mTextureNormal;
@@ -840,7 +841,7 @@ void GuiPopUpMenuCtrlEx::addEntry(const char *buf, S32 id, U32 scheme)
       mIdMax = id;
 
    Entry e;
-   dStrcpy( e.buf, buf );
+   dStrcpy( e.buf, buf, 256 );
    e.id = id;
    e.scheme = scheme;
 

+ 1 - 1
Engine/source/gui/controls/guiTabPageCtrl.cpp

@@ -50,7 +50,7 @@ GuiTabPageCtrl::GuiTabPageCtrl(void)
 {
    setExtent(Point2I(100, 200));
    mFitBook = false;
-   dStrcpy(mText,(UTF8*)"TabPage");
+   dStrcpy(mText,(UTF8*)"TabPage", MAX_STRING_LENGTH);
    mActive = true;
    mIsContainer = true;
 }

+ 4 - 4
Engine/source/gui/controls/guiTreeViewCtrl.cpp

@@ -4750,15 +4750,15 @@ StringTableEntry GuiTreeViewCtrl::getTextToRoot( S32 itemId, const char * delimi
    dMemset( bufferOne, 0, sizeof(bufferOne) );
    dMemset( bufferTwo, 0, sizeof(bufferTwo) );
 
-   dStrcpy( bufferOne, item->getText() );
+   dStrcpy( bufferOne, item->getText(), 1024 );
 
    Item *prevNode = item->mParent;
    while ( prevNode )
    {
       dMemset( bufferNodeText, 0, sizeof(bufferNodeText) );
-      dStrcpy( bufferNodeText, prevNode->getText() );
+      dStrcpy( bufferNodeText, prevNode->getText(), 128 );
       dSprintf( bufferTwo, 1024, "%s%s%s",bufferNodeText, delimiter, bufferOne );
-      dStrcpy( bufferOne, bufferTwo );
+      dStrcpy( bufferOne, bufferTwo, 1024 );
       dMemset( bufferTwo, 0, sizeof(bufferTwo) );
       prevNode = prevNode->mParent;
    }
@@ -5566,4 +5566,4 @@ DefineEngineMethod(GuiTreeViewCtrl, getItemAtPosition, S32, (Point2I position),
    "@return The id of the item under the position.")
 {
    return object->getItemAtPosition(position);
-}
+}

+ 1 - 1
Engine/source/gui/core/guiControl.cpp

@@ -2570,7 +2570,7 @@ DefineEngineMethod( GuiControl, findHitControls, const char*, ( S32 x, S32 y, S3
       return "";
    
    char* buffer = Con::getReturnBuffer( s.size() );
-   dStrcpy( buffer, s.c_str() );
+   dStrcpy( buffer, s.c_str(), s.size() );
    
    return buffer;
 }

+ 3 - 3
Engine/source/gui/editor/guiDebugger.cpp

@@ -431,7 +431,7 @@ bool DbgFileView::findMouseOverVariable()
    {
       S32 stringPosition = pt.x - gFileXOffset;
       char tempBuf[256], *varNamePtr = &tempBuf[1];
-      dStrcpy(tempBuf, mFileView[cell.y].text);
+      dStrcpy(tempBuf, mFileView[cell.y].text, 256);
 
       //find the current mouse over char
       S32 charNum = findMouseOverChar(mFileView[cell.y].text, stringPosition);
@@ -526,7 +526,7 @@ void DbgFileView::onPreRender()
 {
 	setUpdate();
    char oldVar[256];
-   dStrcpy(oldVar, mMouseOverVariable);
+   dStrcpy(oldVar, mMouseOverVariable, 256);
    bool found = findMouseOverVariable();
    if (found && mPCCurrentLine >= 0)
    {
@@ -685,7 +685,7 @@ void DbgFileView::onRenderCell(Point2I offset, Point2I cell, bool selected, bool
       {
          S32 startPos, endPos;
          char tempBuf[256];
-         dStrcpy(tempBuf, mFileView[cell.y].text);
+         dStrcpy(tempBuf, mFileView[cell.y].text, 256);
 
          //get the end coord
          tempBuf[mBlockEnd] = '\0';

+ 2 - 2
Engine/source/gui/editor/guiEditCtrl.cpp

@@ -2625,8 +2625,8 @@ DefineConsoleMethod( GuiEditCtrl, getSelectionGlobalBounds, const char*, (), , "
    RectI bounds = object->getSelectionGlobalBounds();
    String str = String::ToString( "%i %i %i %i", bounds.point.x, bounds.point.y, bounds.extent.x, bounds.extent.y );
    
-   char* buffer = Con::getReturnBuffer( str.length() );
-   dStrcpy( buffer, str.c_str() );
+   char* buffer = Con::getReturnBuffer( str.size() );
+   dStrcpy( buffer, str.c_str(), str.size() );
    
    return buffer;
 }

+ 3 - 3
Engine/source/gui/editor/guiFilterCtrl.cpp

@@ -70,8 +70,8 @@ DefineConsoleMethod( GuiFilterCtrl, getValue, const char*, (), , "Return a tuple
    for (U32 i=0; i < filter->size(); i++)
    {
       char value[32];
-      dSprintf(value, 31, "%1.5f ", *(filter->begin()+i) );
-      dStrcat(buffer, value);
+      dSprintf(value, 32, "%1.5f ", *(filter->begin()+i) );
+      dStrcat(buffer, value, 32);
    }
 
    return buffer;
@@ -239,7 +239,7 @@ void Filter::set(S32 argc, const char *argv[])
    if (argc == 1)
    {  // in the form of one string "1.0 1.0 1.0"
       char list[1024];
-      dStrcpy(list, *argv);    // strtok modifies the string so we need to copy it
+      dStrcpy(list, *argv, 1024);    // strtok modifies the string so we need to copy it
       char *value = dStrtok(list, " ");
       while (value)
       {

+ 1 - 1
Engine/source/gui/utility/messageVector.cpp

@@ -500,7 +500,7 @@ void MessageVector::insertLine(const U32   position,
 
    U32 len = dStrlen(newMessage) + 1;
    char* copy = new char[len];
-   dStrcpy(copy, newMessage);
+   dStrcpy(copy, newMessage, len);
 
    mMessageLines.insert(position);
    mMessageLines[position].message    = copy;

+ 4 - 4
Engine/source/gui/worldEditor/terrainEditor.cpp

@@ -2495,8 +2495,8 @@ DefineConsoleMethod(TerrainEditor, getTerrainBlocksMaterialList, const char *, (
    ret[0] = 0;
    for(U32 i = 0; i < list.size(); ++i)
    {
-      dStrcat( ret, list[i] );
-      dStrcat( ret, "\n" );
+      dStrcat( ret, list[i], size );
+      dStrcat( ret, "\n", size );
    }
 
    return ret;
@@ -2709,8 +2709,8 @@ DefineConsoleMethod(TerrainEditor, getMaterials, const char *, (), , "() gets th
    ret[0] = 0;
    for(U32 i = 0; i < terr->getMaterialCount(); i++)
    {
-      dStrcat( ret, terr->getMaterialName(i) );
-      dStrcat( ret, "\n" );
+      dStrcat( ret, terr->getMaterialName(i), 4096 );
+      dStrcat( ret, "\n", 4096 );
    }
 
    return ret;

+ 25 - 2
Engine/source/gui/worldEditor/worldEditor.cpp

@@ -3927,15 +3927,38 @@ void WorldEditor::makeSelectionAMesh(const char *filename)
    OptimizedPolyList polyList;
    polyList.setBaseTransform(orientation);
 
+   ColladaUtils::ExportData exportData;
+
    for (S32 i = 0; i < objectList.size(); i++)
    {
       SceneObject *pObj = objectList[i];
-      if (!pObj->buildPolyList(PLC_Export, &polyList, pObj->getWorldBox(), pObj->getWorldSphere()))
+      if (!pObj->buildExportPolyList(&exportData, pObj->getWorldBox(), pObj->getWorldSphere()))
          Con::warnf("colladaExportObjectList() - object %i returned no geometry.", pObj->getId());
    }
 
+   //Now that we have all of our mesh data, process it so we can correctly collapse everything.
+   exportData.processData();
+
+   //recenter generated visual mesh results
+   for (U32 dl = 0; dl < exportData.colMeshes.size(); dl++)
+   {
+      for (U32 pnt = 0; pnt < exportData.colMeshes[dl].mesh.mPoints.size(); pnt++)
+      {
+         exportData.colMeshes[dl].mesh.mPoints[pnt] -= centroid;
+      }
+   }
+
+   //recenter generated collision mesh results
+   for (U32 dl = 0; dl < exportData.detailLevels.size(); dl++)
+   {
+      for (U32 pnt = 0; pnt < exportData.detailLevels[dl].mesh.mPoints.size(); pnt++)
+      {
+         exportData.detailLevels[dl].mesh.mPoints[pnt] -= centroid;
+      }
+   }
+
    // Use a ColladaUtils function to do the actual export to a Collada file
-   ColladaUtils::exportToCollada(filename, polyList);
+   ColladaUtils::exportToCollada(filename, exportData);
    //
 
    // Allocate TSStatic object and add to level.

+ 23 - 16
Engine/source/i18n/lang.cpp

@@ -42,8 +42,9 @@ LangFile::LangFile(const UTF8 *langName /* = NULL */)
 
 	if(langName)
 	{
-		mLangName = new UTF8 [dStrlen(langName) + 1];
-		dStrcpy(mLangName, langName);
+		dsize_t langNameLen = dStrlen(langName) + 1;
+		mLangName = new UTF8 [langNameLen];
+		dStrcpy(mLangName, langName, langNameLen);
 	}
 	else
 		mLangName = NULL;
@@ -136,8 +137,9 @@ const UTF8 * LangFile::getString(U32 id)
 
 U32 LangFile::addString(const UTF8 *str)
 {
-	UTF8 *newstr = new UTF8 [dStrlen(str) + 1];
-	dStrcpy(newstr, str);
+	dsize_t newstrLen = dStrlen(str) + 1;
+	UTF8 *newstr = new UTF8 [newstrLen];
+	dStrcpy(newstr, str, newstrLen);
 	mStringTable.push_back(newstr);
 	return mStringTable.size() - 1;
 }
@@ -156,8 +158,9 @@ void LangFile::setString(U32 id, const UTF8 *str)
 
    SAFE_DELETE_ARRAY(mStringTable[id]);
 
-	UTF8 *newstr = new UTF8 [dStrlen(str) + 1];
-	dStrcpy(newstr, str);
+	dsize_t newstrLen = dStrlen(str) + 1;
+	UTF8 *newstr = new UTF8 [newstrLen];
+	dStrcpy(newstr, str, newstrLen);
 	mStringTable[id] = newstr;
 }
 
@@ -166,8 +169,9 @@ void LangFile::setLangName(const UTF8 *newName)
 	if(mLangName)
 		delete [] mLangName;
 	
-	mLangName = new UTF8 [dStrlen(newName) + 1];
-	dStrcpy(mLangName, newName);
+	dsize_t langNameLen = dStrlen(newName) + 1;
+	mLangName = new UTF8 [langNameLen];
+	dStrcpy(mLangName, newName, langNameLen);
 }
 
 void LangFile::setLangFile(const UTF8 *langFile)
@@ -175,8 +179,9 @@ void LangFile::setLangFile(const UTF8 *langFile)
 	if(mLangFile)
 		delete [] mLangFile;
 	
-	mLangFile = new UTF8 [dStrlen(langFile) + 1];
-	dStrcpy(mLangFile, langFile);
+	dsize_t langFileLen = dStrlen(langFile) + 1;
+	mLangFile = new UTF8 [langFileLen];
+	dStrcpy(mLangFile, langFile, langFileLen);
 }
 
 bool LangFile::activateLanguage()
@@ -349,8 +354,9 @@ DefineConsoleMethod(LangTable, getString, const char *, (U32 id), ,
 	const char * str =	(const char*)object->getString(id);
 	if(str != NULL)
 	{
-		char * ret = Con::getReturnBuffer(dStrlen(str) + 1);
-		dStrcpy(ret, str);
+		dsize_t retLen = dStrlen(str) + 1;
+		char * ret = Con::getReturnBuffer(retLen);
+		dStrcpy(ret, str, retLen);
 		return ret;
 	}
 	
@@ -387,8 +393,9 @@ DefineConsoleMethod(LangTable, getLangName, const char *, (S32 langId), , "(int
 	const char * str = (const char*)object->getLangName(langId);
 	if(str != NULL)
 	{
-		char * ret = Con::getReturnBuffer(dStrlen(str) + 1);
-		dStrcpy(ret, str);
+		dsize_t retLen = dStrlen(str) + 1;
+		char * ret = Con::getReturnBuffer(retLen);
+		dStrcpy(ret, str, retLen);
 		return ret;
 	}
 	
@@ -414,7 +421,7 @@ UTF8 *sanitiseVarName(const UTF8 *varName, UTF8 *buffer, U32 bufsize)
 		return NULL;
 	}
 	
-	dStrcpy(buffer, (const UTF8*)"I18N::");
+	dStrcpy(buffer, (const UTF8*)"I18N::", bufsize);
 	
 	UTF8 *dptr = buffer + 6;
 	const UTF8 *sptr = varName;
@@ -575,4 +582,4 @@ ConsoleFunction(CompileLanguage, void, 2, 3, "(string inputFile, [bool createMap
          delete mapStream;
    }
 }
-//end lang_ localization
+//end lang_ localization

+ 10 - 0
Engine/source/main/main.cpp

@@ -283,6 +283,16 @@ int main(int argc, const char **argv)
 #include "app/mainLoop.h"
 #include "T3D/gameFunctions.h"
 
+#if defined(WIN32) || defined(_WIN32) 
+//tell switchable graphics supported systems that they need to use the beefier GPU
+#include <windows.h>
+extern "C" { __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; }
+extern "C" { __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; }
+#else 
+extern "C" { int NvOptimusEnablement = 1; }
+extern "C" { int AmdPowerXpressRequestHighPerformance = 1; }
+#endif
+
 // Entry point for your game.
 //
 // This is build by default using the "StandardMainLoop" toolkit. Feel free

+ 10 - 10
Engine/source/materials/materialDefinition.cpp

@@ -654,35 +654,35 @@ DefineConsoleMethod( Material, getAnimFlags, const char*, (U32 id), , "" )
    if(object->mAnimFlags[ id ] & Material::Scroll)
    {
 	   if(dStrcmp( animFlags, "" ) == 0)
-	      dStrcpy( animFlags, "$Scroll" );
+	      dStrcpy( animFlags, "$Scroll", 512 );
    }
    if(object->mAnimFlags[ id ] & Material::Rotate)
    {
 	   if(dStrcmp( animFlags, "" ) == 0)
-	      dStrcpy( animFlags, "$Rotate" );
+	      dStrcpy( animFlags, "$Rotate", 512 );
 	   else
-			dStrcat( animFlags, " | $Rotate");
+			dStrcat( animFlags, " | $Rotate", 512);
    }
    if(object->mAnimFlags[ id ] & Material::Wave)
    {
 	   if(dStrcmp( animFlags, "" ) == 0)
-	      dStrcpy( animFlags, "$Wave" );
+	      dStrcpy( animFlags, "$Wave", 512 );
 	   else
-			dStrcat( animFlags, " | $Wave");
+			dStrcat( animFlags, " | $Wave", 512);
    }
    if(object->mAnimFlags[ id ] & Material::Scale)
    {
 	   if(dStrcmp( animFlags, "" ) == 0)
-	      dStrcpy( animFlags, "$Scale" );
+	      dStrcpy( animFlags, "$Scale", 512 );
 	   else
-			dStrcat( animFlags, " | $Scale");
+			dStrcat( animFlags, " | $Scale", 512);
    }
    if(object->mAnimFlags[ id ] & Material::Sequence)
    {
 	   if(dStrcmp( animFlags, "" ) == 0)
-	      dStrcpy( animFlags, "$Sequence" );
+	      dStrcpy( animFlags, "$Sequence", 512 );
 	   else
-			dStrcat( animFlags, " | $Sequence");
+			dStrcat( animFlags, " | $Sequence", 512);
    }
 
 	return animFlags;
@@ -718,4 +718,4 @@ bool Material::_setAccuEnabled( void *object, const char *index, const char *dat
       AccumulationVolume::refreshVolumes();
    }
    return true;
-}
+}

+ 3 - 3
Engine/source/module/moduleDefinition.h

@@ -254,11 +254,11 @@ protected:
             for ( U32 dependencyIndex = 0; dependencyIndex < dependencyWordCount; ++dependencyIndex )
             {
                 // Fetch slot.
-                dStrcpy( slotUnit, StringUnit::getUnit( pDependencyValue, dependencyIndex, "," ) );
+                dStrcpy( slotUnit, StringUnit::getUnit( pDependencyValue, dependencyIndex, "," ), 256 );
         
                 // Fetch slot name and value.
-                dStrcpy( slotName, StringUnit::getUnit( slotUnit, 0, "=" ) );
-                dStrcpy( slotValue, StringUnit::getUnit( slotUnit, 1, "=" ) );
+                dStrcpy( slotName, StringUnit::getUnit( slotUnit, 0, "=" ), 256 );
+                dStrcpy( slotValue, StringUnit::getUnit( slotUnit, 1, "=" ), 256 );
 
                 // Fetch module Id.
                 StringTableEntry moduleId = StringTable->insert( slotName );

+ 2 - 2
Engine/source/module/moduleManager.cpp

@@ -74,7 +74,7 @@ ModuleManager::ModuleManager() :
     mIgnoreLoadedGroups(false)
 {
     // Set module extension.
-    dStrcpy( mModuleExtension, MODULE_MANAGER_MODULE_DEFINITION_EXTENSION );
+    dStrcpy( mModuleExtension, MODULE_MANAGER_MODULE_DEFINITION_EXTENSION, 256 );
 }
 
 //-----------------------------------------------------------------------------
@@ -155,7 +155,7 @@ bool ModuleManager::setModuleExtension( const char* pExtension )
     }
 
     // Set module extension.
-    dStrcpy( mModuleExtension, pExtension );
+    dStrcpy( mModuleExtension, pExtension, 256 );
 
     return true;
 }

+ 1 - 1
Engine/source/persistence/taml/fsTinyXml.cpp

@@ -33,7 +33,7 @@ bool fsTiXmlDocument::LoadFile( const char * pFilename, TiXmlEncoding encoding )
 
 #ifdef TORQUE_OS_ANDROID
    if (strlen(pFilename) > strlen(filenameBuffer)) {
-      strcpy(filenameBuffer, pFilename);
+      dStrcpy(filenameBuffer, pFilename, 1024);
    }
 #endif
 

+ 2 - 2
Engine/source/persistence/taml/taml.cpp

@@ -708,7 +708,7 @@ ImplementEnumType(_TamlFormatMode,
 
             U32 nBufferSize = dStrlen(pFieldValue) + 1;
             FrameTemp<char> valueCopy(nBufferSize);
-            dStrcpy((char *)valueCopy, pFieldValue);
+            dStrcpy((char *)valueCopy, pFieldValue, nBufferSize);
 
             // Skip if field should not be written.
             if (!pSimObject->writeField(fieldName, valueCopy))
@@ -1547,4 +1547,4 @@ ImplementEnumType(_TamlFormatMode,
       TiXmlElement* pAnyElement = new TiXmlElement("xs:any");
       pAnyElement->SetAttribute("processContents", "skip");
       pSequenceElement->LinkEndChild(pAnyElement);
-   }
+   }

+ 1 - 1
Engine/source/persistence/taml/tamlCustom.cpp

@@ -53,7 +53,7 @@ void TamlCustomField::set( const char* pFieldName, const char* pFieldValue )
     }
 #endif
     // Copy field value.
-    dStrcpy( mFieldValue, pFieldValue );
+    dStrcpy( mFieldValue, pFieldValue, MAX_TAML_NODE_FIELDVALUE_LENGTH );
 }
 
 //-----------------------------------------------------------------------------

+ 2 - 2
Engine/source/persistence/taml/tamlCustom.h

@@ -334,7 +334,7 @@ public:
         // Sanity!
         AssertFatal( fieldNameLength < sizeof(fieldNameBuffer), "TamlCustomField: Field name is too long." );
 
-        dStrcpy( fieldNameBuffer, mFieldName );
+        dStrcpy( fieldNameBuffer, mFieldName, 1024 );
         fieldNameBuffer[fieldNameLength-1] = 0;
         StringTableEntry fieldName = StringTable->insert( fieldNameBuffer );
 
@@ -782,4 +782,4 @@ private:
     TamlCustomNodeVector mNodes;
 };
 
-#endif // _TAML_CUSTOM_H_
+#endif // _TAML_CUSTOM_H_

+ 4 - 3
Engine/source/persistence/taml/tamlWriteNode.h

@@ -53,8 +53,9 @@ public:
             mName = name;
 
             // Allocate and copy the value.
-            mpValue = new char[ dStrlen(pValue)+1 ];
-            dStrcpy( (char *)mpValue, pValue );
+            dsize_t valueLen = dStrlen(pValue) + 1;
+            mpValue = new char[ valueLen ];
+            dStrcpy( (char *)mpValue, pValue, valueLen );
         }
         
 
@@ -113,4 +114,4 @@ public:
     TamlCustomNodes             mCustomNodes;
 };
 
-#endif // _TAML_WRITE_NODE_H_
+#endif // _TAML_WRITE_NODE_H_

+ 1 - 1
Engine/source/persistence/taml/xml/tamlXmlParser.cpp

@@ -53,7 +53,7 @@ bool TamlXmlParser::accept( const char* pFilename, TamlVisitor& visitor )
 
 #ifdef TORQUE_OS_ANDROID
     if (strlen(pFilename) > strlen(filenameBuffer)) {
-    	strcpy(filenameBuffer, pFilename);
+    	dStrcpy(filenameBuffer, pFilename, 1024);
     }
 #endif
 

+ 1 - 1
Engine/source/platform/input/leapMotion/leapMotionDevice.cpp

@@ -82,7 +82,7 @@ U32 LeapMotionDevice::LM_FRAME = 0;
 LeapMotionDevice::LeapMotionDevice()
 {
    // From IInputDevice
-   dStrcpy(mName, "leapmotion");
+   dStrcpy(mName, "leapmotion", 30);
    mDeviceType = INPUTMGR->getNextDeviceType();
 
    mController = NULL;

+ 1 - 1
Engine/source/platform/input/oculusVR/oculusVRDevice.cpp

@@ -86,7 +86,7 @@ F32 OculusVRDevice::smPositionTrackingScale = 1.0f;
 OculusVRDevice::OculusVRDevice()
 {
    // From IInputDevice
-   dStrcpy(mName, "oculusvr");
+   dStrcpy(mName, "oculusvr", 30);
    mDeviceType = INPUTMGR->getNextDeviceType();
 
    //

+ 1 - 1
Engine/source/platform/input/openVR/openVRProvider.cpp

@@ -493,7 +493,7 @@ OpenVRProvider::OpenVRProvider() :
    mDrawCanvas(NULL),
    mGameConnection(NULL)
 {
-   dStrcpy(mName, "openvr");
+   dStrcpy(mName, "openvr", 30);
    mDeviceType = INPUTMGR->getNextDeviceType();
    buildInputCodeTable();
    GFXDevice::getDeviceEventSignal().notify(this, &OpenVRProvider::_handleDeviceEvent);

+ 1 - 1
Engine/source/platform/input/razerHydra/razerHydraDevice.cpp

@@ -91,7 +91,7 @@ U32 RazerHydraDevice::RH_FRAME = 0;
 RazerHydraDevice::RazerHydraDevice()
 {
    // From IInputDevice
-   dStrcpy(mName, "razerhydra");
+   dStrcpy(mName, "razerhydra", 30);
    mDeviceType = INPUTMGR->getNextDeviceType();
 
    //

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác