From 9b83e47302974f195e202a8a1ac9ddbb1798fc66 Mon Sep 17 00:00:00 2001 From: Areloch Date: Sat, 23 Sep 2017 12:37:55 -0500 Subject: [PATCH 01/26] Adds some filtering options to the console log gui so you can specify if you wish to be able to see errors, warnings and regular messages. It also denotes how many errors and warnings are currently in the log. --- Engine/source/gui/controls/guiConsole.cpp | 190 +++++++++++--- Engine/source/gui/controls/guiConsole.h | 27 ++ .../BaseGame/game/core/console/console.gui | 206 +++++++++++++--- Templates/BaseGame/game/core/console/main.cs | 30 +++ Templates/Full/game/core/art/gui/console.gui | 232 +++++++++++++++--- 5 files changed, 580 insertions(+), 105 deletions(-) diff --git a/Engine/source/gui/controls/guiConsole.cpp b/Engine/source/gui/controls/guiConsole.cpp index 0a1e2459d..19cdf6b3d 100644 --- a/Engine/source/gui/controls/guiConsole.cpp +++ b/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,10 @@ GuiConsole::GuiConsole() setExtent(64, 64); mCellSize.set(1, 1); mSize.set(1, 0); + + mDisplayErrors = true; + mDisplayWarnings = true; + mDisplayNormalMessages = true; } //----------------------------------------------------------------------------- @@ -81,56 +91,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) + { + 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(getParent()); + //first, find out if the console was scrolled up + bool scrolled = false; + GuiScrollCtrl *parent = dynamic_cast(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 +191,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 +201,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 +212,72 @@ 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; + + 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)); +} + +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(); +} \ No newline at end of file diff --git a/Engine/source/gui/controls/guiConsole.h b/Engine/source/gui/controls/guiConsole.h index 8f67573e1..217fe8d6a 100644 --- a/Engine/source/gui/controls/guiConsole.h +++ b/Engine/source/gui/controls/guiConsole.h @@ -39,14 +39,21 @@ class GuiConsole : public GuiArrayCtrl Resource mFont; + bool mDisplayErrors; + bool mDisplayWarnings; + bool mDisplayNormalMessages; + S32 getMaxWidth(S32 startIndex, S32 endIndex); + Vector 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 +70,26 @@ 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 refreshLogText(); }; #endif diff --git a/Templates/BaseGame/game/core/console/console.gui b/Templates/BaseGame/game/core/console/console.gui index 8c6c7f63a..1286ed85c 100644 --- a/Templates/BaseGame/game/core/console/console.gui +++ b/Templates/BaseGame/game/core/console/console.gui @@ -1,51 +1,191 @@ -new GuiControl(ConsoleDlg) { - profile = "GuiDefaultProfile"; +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(ConsoleDlg) { + position = "0 0"; + extent = "1024 768"; + minExtent = "8 8"; horizSizing = "right"; vertSizing = "bottom"; - position = "0 0"; - extent = "640 480"; - minExtent = "8 8"; + profile = "GuiDefaultProfile"; visible = "1"; - helpTag = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + helpTag = "0"; new GuiConsoleEditCtrl(ConsoleEntry) { - profile = "ConsoleTextEditProfile"; - horizSizing = "width"; - vertSizing = "top"; - position = "0 462"; - extent = "640 18"; - minExtent = "8 8"; - visible = "1"; - altCommand = "ConsoleEntry::eval();"; - helpTag = "0"; - maxLength = "255"; + useSiblingScroller = "1"; historySize = "40"; - password = "0"; tabComplete = "0"; sinkAllKeyEvents = "1"; - useSiblingScroller = "1"; + password = "0"; + passwordMask = "*"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 750"; + extent = "1024 18"; + minExtent = "8 8"; + horizSizing = "width"; + vertSizing = "top"; + profile = "ConsoleTextEditProfile"; + visible = "1"; + active = "1"; + altCommand = "ConsoleEntry::eval();"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiContainer() { + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "1 728"; + extent = "1024 22"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "top"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiBitmapCtrl() { + bitmap = "data/ui/art/hudfill.png"; + color = "255 255 255 255"; + wrap = "0"; + position = "0 0"; + extent = "1024 22"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiToggleButtonCtrl(ConsoleDlgErrorFilterBtn) { + text = "Errors"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "2 2"; + extent = "113 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiToggleButtonCtrl(ConsoleDlgWarnFilterBtn) { + text = "Warnings"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "119 2"; + extent = "113 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiToggleButtonCtrl(ConsoleDlgNormalFilterBtn) { + text = "Normal Messages"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "236 2"; + extent = "113 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; new GuiScrollCtrl() { - internalName = "Scroll"; - profile = "ConsoleScrollProfile"; - horizSizing = "width"; - vertSizing = "height"; - position = "0 0"; - extent = "640 462"; - minExtent = "8 8"; - visible = "1"; - helpTag = "0"; willFirstRespond = "1"; hScrollBar = "alwaysOn"; vScrollBar = "alwaysOn"; - lockHorizScroll = "false"; - lockVertScroll = "false"; + lockHorizScroll = "0"; + lockVertScroll = "0"; constantThumbHeight = "0"; childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 0"; + extent = "1024 730"; + minExtent = "8 8"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ConsoleScrollProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "Scroll"; + canSave = "1"; + canSaveDynamicFields = "0"; - new GuiConsole( ConsoleMessageLogView ) { - profile = "GuiConsoleProfile"; - position = "0 0"; - }; + new GuiConsole(ConsoleMessageLogView) { + position = "1 1"; + extent = "622 324"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiConsoleProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; }; + }; }; +//--- OBJECT WRITE END --- \ No newline at end of file diff --git a/Templates/BaseGame/game/core/console/main.cs b/Templates/BaseGame/game/core/console/main.cs index b36dafd24..47894f7e4 100644 --- a/Templates/BaseGame/game/core/console/main.cs +++ b/Templates/BaseGame/game/core/console/main.cs @@ -99,6 +99,13 @@ function ConsoleDlg::showWindow(%this) %this-->Scroll.setVisible(true); } +function ConsoleDlg::onWake(%this) +{ + ConsoleDlgErrorFilterBtn.setStateOn(ConsoleMessageLogView.getErrorFilter()); + ConsoleDlgWarnFilterBtn.setStateOn(ConsoleMessageLogView.getWarnFilter()); + ConsoleDlgNormalFilterBtn.setStateOn(ConsoleMessageLogView.getNormalFilter()); +} + function ConsoleDlg::setAlpha( %this, %alpha) { if (%alpha $= "") @@ -106,3 +113,26 @@ function ConsoleDlg::setAlpha( %this, %alpha) else ConsoleScrollProfile.fillColor = getWords($ConsoleDefaultFillColor, 0, 2) SPC %alpha * 255.0; } + +function ConsoleDlgErrorFilterBtn::onClick(%this) +{ + ConsoleMessageLogView.toggleErrorFilter(); +} + +function ConsoleDlgWarnFilterBtn::onClick(%this) +{ + + ConsoleMessageLogView.toggleWarnFilter(); +} + +function ConsoleDlgNormalFilterBtn::onClick(%this) +{ + ConsoleMessageLogView.toggleNormalFilter(); +} + +function ConsoleMessageLogView::onNewMessage(%this, %errorCount, %warnCount, %normalCount) +{ + ConsoleDlgErrorFilterBtn.setText("(" @ %errorCount @ ") Errors"); + ConsoleDlgWarnFilterBtn.setText("(" @ %warnCount @ ") Warnings"); + ConsoleDlgNormalFilterBtn.setText("(" @ %normalCount @ ") Messages"); +} \ No newline at end of file diff --git a/Templates/Full/game/core/art/gui/console.gui b/Templates/Full/game/core/art/gui/console.gui index 70e5fb61b..c1627fafb 100644 --- a/Templates/Full/game/core/art/gui/console.gui +++ b/Templates/Full/game/core/art/gui/console.gui @@ -1,54 +1,192 @@ //--- OBJECT WRITE BEGIN --- %guiContent = new GuiControl(ConsoleDlg) { - profile = "GuiDefaultProfile"; + position = "0 0"; + extent = "1024 768"; + minExtent = "8 8"; horizSizing = "right"; vertSizing = "bottom"; - position = "0 0"; - extent = "640 480"; - minExtent = "8 8"; + profile = "GuiDefaultProfile"; visible = "1"; - helpTag = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + helpTag = "0"; new GuiConsoleEditCtrl(ConsoleEntry) { - profile = "ConsoleTextEditProfile"; - horizSizing = "width"; - vertSizing = "top"; - position = "0 462"; - extent = "640 18"; - minExtent = "8 8"; - visible = "1"; - altCommand = "ConsoleEntry::eval();"; - helpTag = "0"; - maxLength = "255"; + useSiblingScroller = "1"; historySize = "40"; - password = "0"; tabComplete = "0"; sinkAllKeyEvents = "1"; - useSiblingScroller = "1"; + password = "0"; + passwordMask = "*"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 750"; + extent = "1024 18"; + minExtent = "8 8"; + horizSizing = "width"; + vertSizing = "top"; + profile = "ConsoleTextEditProfile"; + visible = "1"; + active = "1"; + altCommand = "ConsoleEntry::eval();"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiContainer() { + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "1 728"; + extent = "1024 22"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "top"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiBitmapCtrl() { + bitmap = "data/ui/art/hudfill.png"; + color = "255 255 255 255"; + wrap = "0"; + position = "0 0"; + extent = "1024 22"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiToggleButtonCtrl(ConsoleDlgErrorFilterBtn) { + text = "Errors"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "2 2"; + extent = "113 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiToggleButtonCtrl(ConsoleDlgWarnFilterBtn) { + text = "Warnings"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "119 2"; + extent = "113 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiToggleButtonCtrl(ConsoleDlgNormalFilterBtn) { + text = "Normal Messages"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "236 2"; + extent = "113 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; new GuiScrollCtrl() { - internalName = "Scroll"; - profile = "ConsoleScrollProfile"; - horizSizing = "width"; - vertSizing = "height"; - position = "0 0"; - extent = "640 462"; - minExtent = "8 8"; - visible = "1"; - helpTag = "0"; willFirstRespond = "1"; hScrollBar = "alwaysOn"; vScrollBar = "alwaysOn"; - lockHorizScroll = "false"; - lockVertScroll = "false"; + lockHorizScroll = "0"; + lockVertScroll = "0"; constantThumbHeight = "0"; childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 0"; + extent = "1024 730"; + minExtent = "8 8"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ConsoleScrollProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "Scroll"; + canSave = "1"; + canSaveDynamicFields = "0"; - new GuiConsole( ConsoleMessageLogView ) { - profile = "GuiConsoleProfile"; - position = "0 0"; - }; + new GuiConsole(ConsoleMessageLogView) { + position = "1 1"; + extent = "622 324"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiConsoleProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; }; + }; }; //--- OBJECT WRITE END --- @@ -173,3 +311,33 @@ function ConsoleMessageLogView::onMessageSelected( %this, %level, %message ) EditorOpenFileInTorsion( %fileName, %lineNumber ); } + +function ConsoleDlg::onWake(%this) +{ + ConsoleDlgErrorFilterBtn.setStateOn(ConsoleMessageLogView.getErrorFilter()); + ConsoleDlgWarnFilterBtn.setStateOn(ConsoleMessageLogView.getWarnFilter()); + ConsoleDlgNormalFilterBtn.setStateOn(ConsoleMessageLogView.getNormalFilter()); +} + +function ConsoleDlgErrorFilterBtn::onClick(%this) +{ + ConsoleMessageLogView.toggleErrorFilter(); +} + +function ConsoleDlgWarnFilterBtn::onClick(%this) +{ + + ConsoleMessageLogView.toggleWarnFilter(); +} + +function ConsoleDlgNormalFilterBtn::onClick(%this) +{ + ConsoleMessageLogView.toggleNormalFilter(); +} + +function ConsoleMessageLogView::onNewMessage(%this, %errorCount, %warnCount, %normalCount) +{ + ConsoleDlgErrorFilterBtn.setText("(" @ %errorCount @ ") Errors"); + ConsoleDlgWarnFilterBtn.setText("(" @ %warnCount @ ") Warnings"); + ConsoleDlgNormalFilterBtn.setText("(" @ %normalCount @ ") Messages"); +} \ No newline at end of file From a36192ffd8f9489c8541e67f109facb83b0302d3 Mon Sep 17 00:00:00 2001 From: Areloch Date: Thu, 26 Oct 2017 20:11:35 -0500 Subject: [PATCH 02/26] Makes it properly force an update of the filter via a dirty flag. --- Engine/source/gui/controls/guiConsole.cpp | 6 +++++- Engine/source/gui/controls/guiConsole.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Engine/source/gui/controls/guiConsole.cpp b/Engine/source/gui/controls/guiConsole.cpp index 19cdf6b3d..b8987e8df 100644 --- a/Engine/source/gui/controls/guiConsole.cpp +++ b/Engine/source/gui/controls/guiConsole.cpp @@ -68,6 +68,7 @@ GuiConsole::GuiConsole() mDisplayErrors = true; mDisplayWarnings = true; mDisplayNormalMessages = true; + mFiltersDirty = true; } //----------------------------------------------------------------------------- @@ -108,7 +109,7 @@ void GuiConsole::refreshLogText() Con::getLockLog(log, size); - if (mFilteredLog.size() != size) + if (mFilteredLog.size() != size || mFiltersDirty) { mFilteredLog.clear(); @@ -221,6 +222,7 @@ void GuiConsole::setDisplayFilters(bool errors, bool warns, bool normal) mDisplayErrors = errors; mDisplayWarnings = warns; mDisplayNormalMessages = normal; + mFiltersDirty = true; refreshLogText(); @@ -235,6 +237,8 @@ void GuiConsole::setDisplayFilters(bool errors, bool warns, bool normal) 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), diff --git a/Engine/source/gui/controls/guiConsole.h b/Engine/source/gui/controls/guiConsole.h index 217fe8d6a..8b9450e09 100644 --- a/Engine/source/gui/controls/guiConsole.h +++ b/Engine/source/gui/controls/guiConsole.h @@ -42,6 +42,7 @@ class GuiConsole : public GuiArrayCtrl bool mDisplayErrors; bool mDisplayWarnings; bool mDisplayNormalMessages; + bool mFiltersDirty; S32 getMaxWidth(S32 startIndex, S32 endIndex); From 9c3687b8397d0ecc09d3cdaa33c30f188997adef Mon Sep 17 00:00:00 2001 From: Areloch Date: Wed, 15 Nov 2017 18:52:41 -0600 Subject: [PATCH 03/26] Changes the buttons to be a checkbox button, which is easier to identity as being activated or not compared to the stock togglebutton. --- Templates/BaseGame/game/core/console/console.gui | 12 ++++++------ Templates/Full/game/core/art/gui/console.gui | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Templates/BaseGame/game/core/console/console.gui b/Templates/BaseGame/game/core/console/console.gui index 1286ed85c..c2f21eba9 100644 --- a/Templates/BaseGame/game/core/console/console.gui +++ b/Templates/BaseGame/game/core/console/console.gui @@ -83,7 +83,7 @@ canSave = "1"; canSaveDynamicFields = "0"; }; - new GuiToggleButtonCtrl(ConsoleDlgErrorFilterBtn) { + new GuiCheckBoxCtrl(ConsoleDlgErrorFilterBtn) { text = "Errors"; groupNum = "-1"; buttonType = "ToggleButton"; @@ -93,7 +93,7 @@ minExtent = "8 2"; horizSizing = "right"; vertSizing = "bottom"; - profile = "GuiButtonProfile"; + profile = "GuiCheckBoxProfile"; visible = "1"; active = "1"; tooltipProfile = "GuiToolTipProfile"; @@ -102,7 +102,7 @@ canSave = "1"; canSaveDynamicFields = "0"; }; - new GuiToggleButtonCtrl(ConsoleDlgWarnFilterBtn) { + new GuiCheckBoxCtrl(ConsoleDlgWarnFilterBtn) { text = "Warnings"; groupNum = "-1"; buttonType = "ToggleButton"; @@ -112,7 +112,7 @@ minExtent = "8 2"; horizSizing = "right"; vertSizing = "bottom"; - profile = "GuiButtonProfile"; + profile = "GuiCheckBoxProfile"; visible = "1"; active = "1"; tooltipProfile = "GuiToolTipProfile"; @@ -121,7 +121,7 @@ canSave = "1"; canSaveDynamicFields = "0"; }; - new GuiToggleButtonCtrl(ConsoleDlgNormalFilterBtn) { + new GuiCheckBoxCtrl(ConsoleDlgNormalFilterBtn) { text = "Normal Messages"; groupNum = "-1"; buttonType = "ToggleButton"; @@ -131,7 +131,7 @@ minExtent = "8 2"; horizSizing = "right"; vertSizing = "bottom"; - profile = "GuiButtonProfile"; + profile = "GuiCheckBoxProfile"; visible = "1"; active = "1"; tooltipProfile = "GuiToolTipProfile"; diff --git a/Templates/Full/game/core/art/gui/console.gui b/Templates/Full/game/core/art/gui/console.gui index c1627fafb..16300e4ac 100644 --- a/Templates/Full/game/core/art/gui/console.gui +++ b/Templates/Full/game/core/art/gui/console.gui @@ -83,7 +83,7 @@ canSave = "1"; canSaveDynamicFields = "0"; }; - new GuiToggleButtonCtrl(ConsoleDlgErrorFilterBtn) { + new GuiCheckBoxCtrl(ConsoleDlgErrorFilterBtn) { text = "Errors"; groupNum = "-1"; buttonType = "ToggleButton"; @@ -93,7 +93,7 @@ minExtent = "8 2"; horizSizing = "right"; vertSizing = "bottom"; - profile = "GuiButtonProfile"; + profile = "GuiCheckBoxProfile"; visible = "1"; active = "1"; tooltipProfile = "GuiToolTipProfile"; @@ -102,7 +102,7 @@ canSave = "1"; canSaveDynamicFields = "0"; }; - new GuiToggleButtonCtrl(ConsoleDlgWarnFilterBtn) { + new GuiCheckBoxCtrl(ConsoleDlgWarnFilterBtn) { text = "Warnings"; groupNum = "-1"; buttonType = "ToggleButton"; @@ -112,7 +112,7 @@ minExtent = "8 2"; horizSizing = "right"; vertSizing = "bottom"; - profile = "GuiButtonProfile"; + profile = "GuiCheckBoxProfile"; visible = "1"; active = "1"; tooltipProfile = "GuiToolTipProfile"; @@ -121,7 +121,7 @@ canSave = "1"; canSaveDynamicFields = "0"; }; - new GuiToggleButtonCtrl(ConsoleDlgNormalFilterBtn) { + new GuiCheckBoxCtrl(ConsoleDlgNormalFilterBtn) { text = "Normal Messages"; groupNum = "-1"; buttonType = "ToggleButton"; @@ -131,7 +131,7 @@ minExtent = "8 2"; horizSizing = "right"; vertSizing = "bottom"; - profile = "GuiButtonProfile"; + profile = "GuiCheckBoxProfile"; visible = "1"; active = "1"; tooltipProfile = "GuiToolTipProfile"; From c357fdb8974324de055f2b3abe63c12086b5051f Mon Sep 17 00:00:00 2001 From: Marc Chapman Date: Sun, 11 Feb 2018 14:14:47 +0000 Subject: [PATCH 04/26] ShaderModelAutoGen --- .../BaseGame/game/core/shaders/postFX/ssao/SSAO_Blur_P.hlsl | 2 +- Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_P.hlsl | 2 +- Templates/Full/game/shaders/common/postFx/ssao/SSAO_Blur_P.hlsl | 2 +- Templates/Full/game/shaders/common/postFx/ssao/SSAO_P.hlsl | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_Blur_P.hlsl b/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_Blur_P.hlsl index a47261397..5bdf9a77d 100644 --- a/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_Blur_P.hlsl +++ b/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_Blur_P.hlsl @@ -20,7 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "../../ShaderModelAutoGen.hlsl" +#include "../../shaderModelAutoGen.hlsl" #include "./../postFx.hlsl" TORQUE_UNIFORM_SAMPLER2D(occludeMap, 0); diff --git a/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_P.hlsl b/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_P.hlsl index 67365e846..ff31a4b8b 100644 --- a/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_P.hlsl +++ b/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_P.hlsl @@ -20,7 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "../../ShaderModelAutoGen.hlsl" +#include "../../shaderModelAutoGen.hlsl" #include "./../postFx.hlsl" #define DOSMALL diff --git a/Templates/Full/game/shaders/common/postFx/ssao/SSAO_Blur_P.hlsl b/Templates/Full/game/shaders/common/postFx/ssao/SSAO_Blur_P.hlsl index a47261397..5bdf9a77d 100644 --- a/Templates/Full/game/shaders/common/postFx/ssao/SSAO_Blur_P.hlsl +++ b/Templates/Full/game/shaders/common/postFx/ssao/SSAO_Blur_P.hlsl @@ -20,7 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "../../ShaderModelAutoGen.hlsl" +#include "../../shaderModelAutoGen.hlsl" #include "./../postFx.hlsl" TORQUE_UNIFORM_SAMPLER2D(occludeMap, 0); diff --git a/Templates/Full/game/shaders/common/postFx/ssao/SSAO_P.hlsl b/Templates/Full/game/shaders/common/postFx/ssao/SSAO_P.hlsl index 67365e846..ff31a4b8b 100644 --- a/Templates/Full/game/shaders/common/postFx/ssao/SSAO_P.hlsl +++ b/Templates/Full/game/shaders/common/postFx/ssao/SSAO_P.hlsl @@ -20,7 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "../../ShaderModelAutoGen.hlsl" +#include "../../shaderModelAutoGen.hlsl" #include "./../postFx.hlsl" #define DOSMALL From 7b36a618a6c11fdd4ca287bf9b25ec65801a42e6 Mon Sep 17 00:00:00 2001 From: Marc Chapman Date: Sun, 11 Feb 2018 14:29:39 +0000 Subject: [PATCH 05/26] PostFX.hlsl --- Templates/BaseGame/game/core/shaders/postFX/fxaa/fxaaV.hlsl | 2 +- Templates/Full/game/shaders/common/postFx/fxaa/fxaaV.hlsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Templates/BaseGame/game/core/shaders/postFX/fxaa/fxaaV.hlsl b/Templates/BaseGame/game/core/shaders/postFX/fxaa/fxaaV.hlsl index 3bef0a4d3..f2974c587 100644 --- a/Templates/BaseGame/game/core/shaders/postFX/fxaa/fxaaV.hlsl +++ b/Templates/BaseGame/game/core/shaders/postFX/fxaa/fxaaV.hlsl @@ -21,7 +21,7 @@ //----------------------------------------------------------------------------- #include "./../../torque.hlsl" -#include "./../postFX.hlsl" +#include "./../postFx.hlsl" struct VertToPix { diff --git a/Templates/Full/game/shaders/common/postFx/fxaa/fxaaV.hlsl b/Templates/Full/game/shaders/common/postFx/fxaa/fxaaV.hlsl index 3bef0a4d3..f2974c587 100644 --- a/Templates/Full/game/shaders/common/postFx/fxaa/fxaaV.hlsl +++ b/Templates/Full/game/shaders/common/postFx/fxaa/fxaaV.hlsl @@ -21,7 +21,7 @@ //----------------------------------------------------------------------------- #include "./../../torque.hlsl" -#include "./../postFX.hlsl" +#include "./../postFx.hlsl" struct VertToPix { From 54426f12955c21f98c9af7df827a54dc09f66d0a Mon Sep 17 00:00:00 2001 From: Marc Chapman Date: Sun, 11 Feb 2018 17:27:04 +0000 Subject: [PATCH 06/26] rock_* fixes --- .../game/art/shapes/weapons/Grenade/materials.cs | 8 ++++---- .../Grenade/{rock_diffuse.DDS => rock_d.dds} | Bin .../Grenade/{rock_normals.DDS => rock_n.dds} | Bin .../Grenade/{rock_specular.DDS => rock_s.dds} | Bin 4 files changed, 4 insertions(+), 4 deletions(-) rename Templates/Full/game/art/shapes/weapons/Grenade/{rock_diffuse.DDS => rock_d.dds} (100%) rename Templates/Full/game/art/shapes/weapons/Grenade/{rock_normals.DDS => rock_n.dds} (100%) rename Templates/Full/game/art/shapes/weapons/Grenade/{rock_specular.DDS => rock_s.dds} (100%) diff --git a/Templates/Full/game/art/shapes/weapons/Grenade/materials.cs b/Templates/Full/game/art/shapes/weapons/Grenade/materials.cs index 569f28ed0..ba26267da 100644 --- a/Templates/Full/game/art/shapes/weapons/Grenade/materials.cs +++ b/Templates/Full/game/art/shapes/weapons/Grenade/materials.cs @@ -49,11 +49,11 @@ singleton Material(debri_debris) { mapTo = "debris"; diffuseColor[0] = "0.7 0.7 0.7 1"; - diffuseMap[0] = "rock_diffuse.dds"; - normalMap[0] = "rock_normals.dds"; + diffuseMap[0] = "rock_d"; + normalMap[0] = "rock_n"; + specularMap[0] = "rock_s"; specular[0] = "1 1 1 0"; - specularPower[0] = "50"; - specularMap[0] = "rock_specular.dds"; + specularPower[0] = "50"; castShadows = "0"; translucentBlendOp = "None"; materialTag0 = "Weapon"; diff --git a/Templates/Full/game/art/shapes/weapons/Grenade/rock_diffuse.DDS b/Templates/Full/game/art/shapes/weapons/Grenade/rock_d.dds similarity index 100% rename from Templates/Full/game/art/shapes/weapons/Grenade/rock_diffuse.DDS rename to Templates/Full/game/art/shapes/weapons/Grenade/rock_d.dds diff --git a/Templates/Full/game/art/shapes/weapons/Grenade/rock_normals.DDS b/Templates/Full/game/art/shapes/weapons/Grenade/rock_n.dds similarity index 100% rename from Templates/Full/game/art/shapes/weapons/Grenade/rock_normals.DDS rename to Templates/Full/game/art/shapes/weapons/Grenade/rock_n.dds diff --git a/Templates/Full/game/art/shapes/weapons/Grenade/rock_specular.DDS b/Templates/Full/game/art/shapes/weapons/Grenade/rock_s.dds similarity index 100% rename from Templates/Full/game/art/shapes/weapons/Grenade/rock_specular.DDS rename to Templates/Full/game/art/shapes/weapons/Grenade/rock_s.dds From ff2d18cc076c1734bb92a044805220c7891bf033 Mon Sep 17 00:00:00 2001 From: Azaezel Date: Mon, 26 Feb 2018 20:45:18 -0600 Subject: [PATCH 07/26] tell switchable graphics supported systems that they need to use the beefier GPU --- Engine/source/main/main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Engine/source/main/main.cpp b/Engine/source/main/main.cpp index f74430fc1..b5fea8a07 100644 --- a/Engine/source/main/main.cpp +++ b/Engine/source/main/main.cpp @@ -283,6 +283,14 @@ 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 +extern "C" { __declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001; } +extern "C" { __declspec(dllexport) unsigned long 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 From 488fba16c12feb319d598fa9b77a0e3f5ceab15a Mon Sep 17 00:00:00 2001 From: Azaezel Date: Mon, 26 Feb 2018 22:34:21 -0600 Subject: [PATCH 08/26] requested revision: use dword just in case of compiler shenanigans --- Engine/source/main/main.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Engine/source/main/main.cpp b/Engine/source/main/main.cpp index b5fea8a07..ad3556913 100644 --- a/Engine/source/main/main.cpp +++ b/Engine/source/main/main.cpp @@ -283,9 +283,11 @@ 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 -extern "C" { __declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001; } -extern "C" { __declspec(dllexport) unsigned long AmdPowerXpressRequestHighPerformance = 0x00000001; } +#if defined(WIN32) || defined(_WIN32) +//tell switchable graphics supported systems that they need to use the beefier GPU +#include +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; } From 49639a908f0e91760fae4f04a66be9e60145905d Mon Sep 17 00:00:00 2001 From: Areloch Date: Thu, 1 Mar 2018 01:51:18 -0600 Subject: [PATCH 09/26] Expanded mesh baking functionality, now supporting baking of LODs and Collision meshes --- Engine/source/T3D/tsStatic.cpp | 101 ++ Engine/source/T3D/tsStatic.h | 3 + Engine/source/gui/worldEditor/worldEditor.cpp | 27 +- Engine/source/scene/sceneObject.h | 21 + Engine/source/ts/collada/colladaUtils.cpp | 1283 ++++++++++++++++- Engine/source/ts/collada/colladaUtils.h | 137 +- Engine/source/ts/tsShapeConstruct.cpp | 14 + 7 files changed, 1578 insertions(+), 8 deletions(-) diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 13964e632..9eaab881b 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -1073,6 +1073,97 @@ bool TSStatic::buildPolyList(PolyListContext context, AbstractPolyList* polyList return true; } +bool TSStatic::buildExportPolyList(PolyListContext context, 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(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(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 diff --git a/Engine/source/T3D/tsStatic.h b/Engine/source/T3D/tsStatic.h index 224086c71..2df45a861 100644 --- a/Engine/source/T3D/tsStatic.h +++ b/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(PolyListContext context, 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& getCollisionDetails() const { return mCollisionDetails; } const Vector& getLOSDetails() const { return mLOSDetails; } diff --git a/Engine/source/gui/worldEditor/worldEditor.cpp b/Engine/source/gui/worldEditor/worldEditor.cpp index 7846ec094..ca6c966ae 100644 --- a/Engine/source/gui/worldEditor/worldEditor.cpp +++ b/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(PLC_Export, &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. diff --git a/Engine/source/scene/sceneObject.h b/Engine/source/scene/sceneObject.h index 549246c9e..3e7fab355 100644 --- a/Engine/source/scene/sceneObject.h +++ b/Engine/source/scene/sceneObject.h @@ -60,6 +60,9 @@ #include "gfx/gfxDevice.h" #endif +#ifndef _COLLADA_UTILS_H_ +#include "ts/collada/colladaUtils.h" +#endif class SceneManager; class SceneRenderState; @@ -550,6 +553,24 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce const Box3F& box, const SphereF& sphere ) { return false; } + /// Builds a list of polygons which intersect a bounding volume for exporting + /// + /// This will use either the sphere or the box, not both, the + /// SceneObject implementation ignores sphere. + /// + /// @see AbstractPolyList + /// @param context A contentual hint as to the type of polylist to build. + /// @param polyList Poly list build (out) + /// @param box Box bounding volume + /// @param sphere Sphere bounding volume + /// + virtual bool buildExportPolyList(PolyListContext context, + ColladaUtils::ExportData *exportData, + const Box3F& box, + const SphereF& sphere) { + return false; + } + /// Casts a ray and obtain collision information, returns true if RayInfo is modified. /// /// @param start Start point of ray diff --git a/Engine/source/ts/collada/colladaUtils.cpp b/Engine/source/ts/collada/colladaUtils.cpp index e88abe372..32c559077 100644 --- a/Engine/source/ts/collada/colladaUtils.cpp +++ b/Engine/source/ts/collada/colladaUtils.cpp @@ -1277,6 +1277,289 @@ void ColladaUtils::exportColladaMaterials(TiXmlElement* rootNode, const Optimize } +void ColladaUtils::exportColladaMaterials(TiXmlElement* rootNode, const ExportData& exportData, const Torque::Path& colladaFile) +{ + // First the image library + TiXmlElement* imgLibNode = new TiXmlElement("library_images"); + rootNode->LinkEndChild(imgLibNode); + + Vector matNames; + + for (U32 i = 0; i < exportData.materials.size(); i++) + { + BaseMatInstance* baseInst = exportData.materials[i]; + + matNames.push_back(String::ToString("Material%d", i)); + + Material* mat = dynamic_cast(baseInst->getMaterial()); + if (!mat) + continue; + + String diffuseMap; + + if (mat->getName() && mat->getName()[0]) + matNames.last() = mat->mMapTo; + + // Handle an auto-generated "Default Material" specially + if (mat->isAutoGenerated()) + { + Torque::Path diffusePath; + + if (mat->mDiffuseMapFilename[0].isNotEmpty()) + diffusePath = mat->mDiffuseMapFilename[0]; + else + diffusePath = String("warningMat"); + + matNames.last() = diffusePath.getFileName(); + diffuseMap += diffusePath.getFullFileName(); + } + else + { + if (mat->mDiffuseMapFilename[0].isNotEmpty()) + diffuseMap += mat->mDiffuseMapFilename[0]; + else + diffuseMap += "warningMat"; + } + + Torque::Path diffusePath = findTexture(colladaFile.getPath() + "/" + diffuseMap); + + // If we didn't get a path + if (diffusePath.getFullPath().isNotEmpty()) + diffuseMap = Torque::Path::MakeRelativePath(diffusePath, colladaFile); + + TiXmlElement* imageNode = new TiXmlElement("image"); + imgLibNode->LinkEndChild(imageNode); + imageNode->SetAttribute("id", avar("%s", matNames.last().c_str())); + imageNode->SetAttribute("name", avar("%s", matNames.last().c_str())); + + TiXmlElement* initNode = new TiXmlElement("init_from"); + imageNode->LinkEndChild(initNode); + TiXmlText* initText = new TiXmlText(avar("file://%s", diffuseMap.c_str())); // "the file://" is needed to load the texture in some old apps (ex: 3ds Max 2009) + initNode->LinkEndChild(initText); + } + + // Next the effects library + TiXmlElement* effectLibNode = new TiXmlElement("library_effects"); + rootNode->LinkEndChild(effectLibNode); + + for (U32 i = 0; i < exportData.materials.size(); i++) + { + BaseMatInstance* baseInst = exportData.materials[i]; + + Material* mat = dynamic_cast(baseInst->getMaterial()); + if (!mat) + continue; + + TiXmlElement* effectNode = new TiXmlElement("effect"); + effectLibNode->LinkEndChild(effectNode); + effectNode->SetAttribute("id", avar("%s-effect", matNames[i].c_str())); + effectNode->SetAttribute("name", avar("%s-effect", matNames[i].c_str())); + + TiXmlElement* profileNode = new TiXmlElement("profile_COMMON"); + effectNode->LinkEndChild(profileNode); + + // --------------------------- + TiXmlElement* newParamNode = new TiXmlElement("newparam"); + profileNode->LinkEndChild(newParamNode); + newParamNode->SetAttribute("sid", avar("%s-surface", matNames[i].c_str())); + + TiXmlElement* surfaceNode = new TiXmlElement("surface"); + newParamNode->LinkEndChild(surfaceNode); + surfaceNode->SetAttribute("type", "2D"); + + TiXmlElement* initNode2 = new TiXmlElement("init_from"); + surfaceNode->LinkEndChild(initNode2); + TiXmlText* init2Text = new TiXmlText(avar("%s", matNames[i].c_str())); + initNode2->LinkEndChild(init2Text); + + TiXmlElement* formatNode = new TiXmlElement("format"); + surfaceNode->LinkEndChild(formatNode); + TiXmlText* formatText = new TiXmlText("A8R8G8B8"); + formatNode->LinkEndChild(formatText); + + // --------------------------- + TiXmlElement* newParam2Node = new TiXmlElement("newparam"); + profileNode->LinkEndChild(newParam2Node); + newParam2Node->SetAttribute("sid", avar("%s-sampler", matNames[i].c_str())); + + TiXmlElement* sampler2DNode = new TiXmlElement("sampler2D"); + newParam2Node->LinkEndChild(sampler2DNode); + + TiXmlElement* sourceSampler2DNode = new TiXmlElement("source"); + sampler2DNode->LinkEndChild(sourceSampler2DNode); + TiXmlText* sourceSampler2DText = new TiXmlText(avar("%s-surface", matNames[i].c_str())); + sourceSampler2DNode->LinkEndChild(sourceSampler2DText); + + // --------------------------- + + TiXmlElement* techniqueNode = new TiXmlElement("technique"); + profileNode->LinkEndChild(techniqueNode); + techniqueNode->SetAttribute("sid", "common"); + + TiXmlElement* blinnNode = new TiXmlElement("blinn"); + techniqueNode->LinkEndChild(blinnNode); + + // --------------------------- + TiXmlElement* emissionNode = new TiXmlElement("emission"); + blinnNode->LinkEndChild(emissionNode); + + TiXmlElement* colorEmissionNode = new TiXmlElement("color"); + emissionNode->LinkEndChild(colorEmissionNode); + colorEmissionNode->SetAttribute("sid", "emission"); + + TiXmlText* colorEmissionNodeText = new TiXmlText("0.0 0.0 0.0 1.0"); + colorEmissionNode->LinkEndChild(colorEmissionNodeText); + + // --------------------------- + TiXmlElement* ambientNode = new TiXmlElement("ambient"); + blinnNode->LinkEndChild(ambientNode); + + TiXmlElement* colorAmbientNode = new TiXmlElement("color"); + ambientNode->LinkEndChild(colorAmbientNode); + colorAmbientNode->SetAttribute("sid", "ambient"); + + TiXmlText* colorAmbientNodeText = new TiXmlText("0.0 0.0 0.0 1.0"); + colorAmbientNode->LinkEndChild(colorAmbientNodeText); + + // --------------------------- + TiXmlElement* diffuseNode = new TiXmlElement("diffuse"); + blinnNode->LinkEndChild(diffuseNode); + TiXmlElement* textureDiffuseNode = new TiXmlElement("texture"); + diffuseNode->LinkEndChild(textureDiffuseNode); + textureDiffuseNode->SetAttribute("texture", avar("%s-sampler", matNames[i].c_str())); + textureDiffuseNode->SetAttribute("texcoord", "UVMap"); + + // Extra info useful for getting the texture to show up correctly in MAYA and 3DS Max + TiXmlElement* extraNode = new TiXmlElement("extra"); + textureDiffuseNode->LinkEndChild(extraNode); + + TiXmlElement* extraTechNode = new TiXmlElement("technique"); + extraNode->LinkEndChild(extraTechNode); + extraTechNode->SetAttribute("profile", "MAYA"); + + TiXmlElement* extraWrapUNode = new TiXmlElement("wrapU"); + extraTechNode->LinkEndChild(extraWrapUNode); + extraWrapUNode->SetAttribute("sid", "wrapU0"); + + TiXmlText* extraWrapUText = new TiXmlText("TRUE"); + extraWrapUNode->LinkEndChild(extraWrapUText); + + TiXmlElement* extraWrapVNode = new TiXmlElement("wrapV"); + extraTechNode->LinkEndChild(extraWrapVNode); + extraWrapVNode->SetAttribute("sid", "wrapV0"); + + TiXmlText* extraWrapVText = new TiXmlText("TRUE"); + extraWrapVNode->LinkEndChild(extraWrapVText); + + TiXmlElement* extraBlendNode = new TiXmlElement("blend_mode"); + extraTechNode->LinkEndChild(extraBlendNode); + + TiXmlText* extraBlendText = new TiXmlText("ADD"); + extraBlendNode->LinkEndChild(extraBlendText); + + // --------------------------- + TiXmlElement* specularNode = new TiXmlElement("specular"); + blinnNode->LinkEndChild(specularNode); + + TiXmlElement* colorSpecularNode = new TiXmlElement("color"); + specularNode->LinkEndChild(colorSpecularNode); + colorSpecularNode->SetAttribute("sid", "specular"); + + TiXmlText* colorSpecularNodeText = new TiXmlText("0.5 0.5 0.5 1.0"); + colorSpecularNode->LinkEndChild(colorSpecularNodeText); + + // --------------------------- + TiXmlElement* shininessNode = new TiXmlElement("shininess"); + blinnNode->LinkEndChild(shininessNode); + + TiXmlElement* colorShininessNode = new TiXmlElement("float"); + shininessNode->LinkEndChild(colorShininessNode); + colorShininessNode->SetAttribute("sid", "shininess"); + + TiXmlText* colorShininessNodeText = new TiXmlText("1.0"); + colorShininessNode->LinkEndChild(colorShininessNodeText); + + // --------------------------- + TiXmlElement* reflectiveNode = new TiXmlElement("reflective"); + blinnNode->LinkEndChild(reflectiveNode); + + TiXmlElement* colorReflectiveNode = new TiXmlElement("color"); + reflectiveNode->LinkEndChild(colorReflectiveNode); + colorReflectiveNode->SetAttribute("sid", "reflective"); + + TiXmlText* colorReflectiveNodeText = new TiXmlText("0.0 0.0 0.0 1.0"); + colorReflectiveNode->LinkEndChild(colorReflectiveNodeText); + + // --------------------------- + TiXmlElement* reflectivityNode = new TiXmlElement("reflectivity"); + blinnNode->LinkEndChild(reflectivityNode); + + TiXmlElement* floatReflectivityNode = new TiXmlElement("float"); + reflectivityNode->LinkEndChild(floatReflectivityNode); + floatReflectivityNode->SetAttribute("sid", "reflectivity"); + + TiXmlText* floatReflectivityText = new TiXmlText("0.5"); + floatReflectivityNode->LinkEndChild(floatReflectivityText); + + // --------------------------- + TiXmlElement* transparentNode = new TiXmlElement("transparent"); + blinnNode->LinkEndChild(transparentNode); + transparentNode->SetAttribute("opaque", "RGB_ZERO"); + + TiXmlElement* colorTransparentNode = new TiXmlElement("color"); + transparentNode->LinkEndChild(colorTransparentNode); + colorTransparentNode->SetAttribute("sid", "transparent"); + + TiXmlText* colorTransparentNodeText = new TiXmlText("0.0 0.0 0.0 1.0"); + colorTransparentNode->LinkEndChild(colorTransparentNodeText); + + // --------------------------- + TiXmlElement* transparencyNode = new TiXmlElement("transparency"); + blinnNode->LinkEndChild(transparencyNode); + + TiXmlElement* floatTransparencyNode = new TiXmlElement("float"); + transparencyNode->LinkEndChild(floatTransparencyNode); + floatTransparencyNode->SetAttribute("sid", "transparency"); + + TiXmlText* floatTransparencyText = new TiXmlText("0.0"); + floatTransparencyNode->LinkEndChild(floatTransparencyText); + + // --------------------------- + TiXmlElement* refractionNode = new TiXmlElement("index_of_refraction"); + blinnNode->LinkEndChild(refractionNode); + + TiXmlElement* colorRefractionNode = new TiXmlElement("float"); + refractionNode->LinkEndChild(colorRefractionNode); + colorRefractionNode->SetAttribute("sid", "index_of_refraction"); + + TiXmlText* colorRefractionNodeText = new TiXmlText("1"); + colorRefractionNode->LinkEndChild(colorRefractionNodeText); + } + + // Finally the material library + TiXmlElement* matLibNode = new TiXmlElement("library_materials"); + rootNode->LinkEndChild(matLibNode); + + for (U32 i = 0; i < exportData.materials.size(); i++) + { + BaseMatInstance* baseInst = exportData.materials[i]; + + Material* mat = dynamic_cast(baseInst->getMaterial()); + if (!mat) + continue; + + TiXmlElement* materialNode = new TiXmlElement("material"); + matLibNode->LinkEndChild(materialNode); + materialNode->SetAttribute("id", avar("%s-material", matNames[i].c_str())); + materialNode->SetAttribute("name", matNames[i].c_str()); + + TiXmlElement* instEffectNode = new TiXmlElement("instance_effect"); + materialNode->LinkEndChild(instEffectNode); + instEffectNode->SetAttribute("url", avar("#%s-effect", matNames[i].c_str())); + } + +} + void ColladaUtils::exportColladaTriangles(TiXmlElement* meshNode, const OptimizedPolyList& mesh, const String& meshName, const Vector& matNames) { // Start at -1 so we will export polygons that do not have a material. @@ -1396,6 +1679,252 @@ void ColladaUtils::exportColladaTriangles(TiXmlElement* meshNode, const Optimize } } +void ColladaUtils::exportColladaTriangles(TiXmlElement* meshNode, const ExportData& exportData, const U32 detailLevel, const String& meshName) +{ + // Calculate the number of triangles that uses this Material + U32 triangleCount = 0; + + const ExportData::detailLevel* dl = &exportData.detailLevels[detailLevel]; + + for (S32 i = 0; i < dl->materialRefList.size(); i++) + { + int matIdx; + dl->materialRefList.tryGetValue(i, matIdx); + BaseMatInstance* baseInst = exportData.materials[matIdx]; + + Material* mat = dynamic_cast(baseInst->getMaterial()); + if (!mat) + continue; + + String matName; + + if (mat->getName() && mat->getName()[0]) + matName = mat->mMapTo; + + for (U32 j = 0; j < dl->mesh.mPolyList.size(); j++) + { + const OptimizedPolyList::Poly& poly = dl->mesh.mPolyList[j]; + + if (poly.material != i) + continue; + + if (poly.vertexCount < 3) + continue; + + if (poly.type == OptimizedPolyList::TriangleList || + poly.type == OptimizedPolyList::TriangleFan || + poly.type == OptimizedPolyList::TriangleStrip) + { + triangleCount += poly.vertexCount - 2; + } + else + AssertISV(false, "ColladaUtils::exportColladaTriangles(): Unknown Poly type!"); + } + + // Make sure that we are actually using this Material + if (triangleCount == 0) + continue; + + TiXmlElement* trianglesNode = new TiXmlElement("triangles"); + meshNode->LinkEndChild(trianglesNode); + trianglesNode->SetAttribute("material", (i > -1) ? avar("%s-material", matName.c_str()) : ""); + trianglesNode->SetAttribute("count", avar("%d", triangleCount)); + + TiXmlElement* trianglesVertInputNode = new TiXmlElement("input"); + trianglesNode->LinkEndChild(trianglesVertInputNode); + trianglesVertInputNode->SetAttribute("semantic", "VERTEX"); + trianglesVertInputNode->SetAttribute("source", avar("#%s-mesh-vertices", meshName.c_str())); + trianglesVertInputNode->SetAttribute("offset", "0"); + + TiXmlElement* trianglesNormalInputNode = new TiXmlElement("input"); + trianglesNode->LinkEndChild(trianglesNormalInputNode); + trianglesNormalInputNode->SetAttribute("semantic", "NORMAL"); + trianglesNormalInputNode->SetAttribute("source", avar("#%s-mesh-normals", meshName.c_str())); + trianglesNormalInputNode->SetAttribute("offset", "1"); + + TiXmlElement* trianglesUV0InputNode = new TiXmlElement("input"); + trianglesNode->LinkEndChild(trianglesUV0InputNode); + trianglesUV0InputNode->SetAttribute("semantic", "TEXCOORD"); + trianglesUV0InputNode->SetAttribute("source", avar("#%s-mesh-map-0", meshName.c_str())); + trianglesUV0InputNode->SetAttribute("offset", "2"); + trianglesUV0InputNode->SetAttribute("set", "0"); + + TiXmlElement* polyNode = new TiXmlElement("p"); + trianglesNode->LinkEndChild(polyNode); + + Vector tempIndices; + tempIndices.reserve(4); + + for (U32 j = 0; j < dl->mesh.mPolyList.size(); j++) + { + const OptimizedPolyList::Poly& poly = dl->mesh.mPolyList[j]; + + if (poly.vertexCount < 3) + continue; + + if (poly.material != i) + continue; + + tempIndices.setSize(poly.vertexCount); + dMemset(tempIndices.address(), 0, poly.vertexCount); + + if (poly.type == OptimizedPolyList::TriangleStrip) + { + tempIndices[0] = 0; + U32 idx = 1; + + for (U32 k = 1; k < poly.vertexCount; k += 2) + tempIndices[idx++] = k; + + for (U32 k = ((poly.vertexCount - 1) & (~0x1)); k > 0; k -= 2) + tempIndices[idx++] = k; + } + else if (poly.type == OptimizedPolyList::TriangleList || + poly.type == OptimizedPolyList::TriangleFan) + { + for (U32 k = 0; k < poly.vertexCount; k++) + tempIndices[k] = k; + } + else + AssertISV(false, "ColladaUtils::exportColladaTriangles(): Unknown Poly type!"); + + const U32& firstIdx = dl->mesh.mIndexList[poly.vertexStart]; + const OptimizedPolyList::VertIndex& firstVertIdx = dl->mesh.mVertexList[firstIdx]; + + for (U32 k = 1; k < poly.vertexCount - 1; k++) + { + const U32& secondIdx = dl->mesh.mIndexList[poly.vertexStart + tempIndices[k]]; + const U32& thirdIdx = dl->mesh.mIndexList[poly.vertexStart + tempIndices[k + 1]]; + + const OptimizedPolyList::VertIndex& secondVertIdx = dl->mesh.mVertexList[secondIdx]; + const OptimizedPolyList::VertIndex& thirdVertIdx = dl->mesh.mVertexList[thirdIdx]; + + // Note the reversed winding on the triangles + const char* tri = avar("%d %d %d %d %d %d %d %d %d ", + thirdVertIdx.vertIdx, thirdVertIdx.normalIdx, thirdVertIdx.uv0Idx, + secondVertIdx.vertIdx, secondVertIdx.normalIdx, secondVertIdx.uv0Idx, + firstVertIdx.vertIdx, firstVertIdx.normalIdx, firstVertIdx.uv0Idx); + + TiXmlText* triangleText = new TiXmlText(tri); + polyNode->LinkEndChild(triangleText); + } + } + } +} + +void ColladaUtils::exportColladaCollisionTriangles(TiXmlElement* meshNode, const ExportData& exportData, const U32 collisionIdx) +{ + // Calculate the number of triangles that uses this Material + U32 triangleCount = 0; + + const ExportData::colMesh* col = &exportData.colMeshes[collisionIdx]; + + String meshName = col->colMeshName; + + for (U32 j = 0; j < col->mesh.mPolyList.size(); j++) + { + const OptimizedPolyList::Poly& poly = col->mesh.mPolyList[j]; + + if (poly.vertexCount < 3) + continue; + + if (poly.type == OptimizedPolyList::TriangleList || + poly.type == OptimizedPolyList::TriangleFan || + poly.type == OptimizedPolyList::TriangleStrip) + { + triangleCount += poly.vertexCount - 2; + } + else + AssertISV(false, "ColladaUtils::exportColladaCollisionTriangles(): Unknown Poly type!"); + } + + // Make sure that we are actually using this Material + if (triangleCount == 0) + return; + + TiXmlElement* trianglesNode = new TiXmlElement("triangles"); + meshNode->LinkEndChild(trianglesNode); + trianglesNode->SetAttribute("material", ""); + trianglesNode->SetAttribute("count", avar("%d", triangleCount)); + + TiXmlElement* trianglesVertInputNode = new TiXmlElement("input"); + trianglesNode->LinkEndChild(trianglesVertInputNode); + trianglesVertInputNode->SetAttribute("semantic", "VERTEX"); + trianglesVertInputNode->SetAttribute("source", avar("#%s-mesh-vertices", meshName.c_str())); + trianglesVertInputNode->SetAttribute("offset", "0"); + + TiXmlElement* trianglesNormalInputNode = new TiXmlElement("input"); + trianglesNode->LinkEndChild(trianglesNormalInputNode); + trianglesNormalInputNode->SetAttribute("semantic", "NORMAL"); + trianglesNormalInputNode->SetAttribute("source", avar("#%s-mesh-normals", meshName.c_str())); + trianglesNormalInputNode->SetAttribute("offset", "1"); + + TiXmlElement* trianglesUV0InputNode = new TiXmlElement("input"); + trianglesNode->LinkEndChild(trianglesUV0InputNode); + trianglesUV0InputNode->SetAttribute("semantic", "TEXCOORD"); + trianglesUV0InputNode->SetAttribute("source", avar("#%s-mesh-map-0", meshName.c_str())); + trianglesUV0InputNode->SetAttribute("offset", "2"); + trianglesUV0InputNode->SetAttribute("set", "0"); + + TiXmlElement* polyNode = new TiXmlElement("p"); + trianglesNode->LinkEndChild(polyNode); + + Vector tempIndices; + tempIndices.reserve(4); + + for (U32 j = 0; j < col->mesh.mPolyList.size(); j++) + { + const OptimizedPolyList::Poly& poly = col->mesh.mPolyList[j]; + + if (poly.vertexCount < 3) + continue; + + tempIndices.setSize(poly.vertexCount); + dMemset(tempIndices.address(), 0, poly.vertexCount); + + if (poly.type == OptimizedPolyList::TriangleStrip) + { + tempIndices[0] = 0; + U32 idx = 1; + + for (U32 k = 1; k < poly.vertexCount; k += 2) + tempIndices[idx++] = k; + + for (U32 k = ((poly.vertexCount - 1) & (~0x1)); k > 0; k -= 2) + tempIndices[idx++] = k; + } + else if (poly.type == OptimizedPolyList::TriangleList || + poly.type == OptimizedPolyList::TriangleFan) + { + for (U32 k = 0; k < poly.vertexCount; k++) + tempIndices[k] = k; + } + else + AssertISV(false, "ColladaUtils::exportColladaTriangles(): Unknown Poly type!"); + + const U32& firstIdx = col->mesh.mIndexList[poly.vertexStart]; + const OptimizedPolyList::VertIndex& firstVertIdx = col->mesh.mVertexList[firstIdx]; + + for (U32 k = 1; k < poly.vertexCount - 1; k++) + { + const U32& secondIdx = col->mesh.mIndexList[poly.vertexStart + tempIndices[k]]; + const U32& thirdIdx = col->mesh.mIndexList[poly.vertexStart + tempIndices[k + 1]]; + + const OptimizedPolyList::VertIndex& secondVertIdx = col->mesh.mVertexList[secondIdx]; + const OptimizedPolyList::VertIndex& thirdVertIdx = col->mesh.mVertexList[thirdIdx]; + + // Note the reversed winding on the triangles + const char* tri = avar("%d %d %d %d %d %d %d %d %d ", + thirdVertIdx.vertIdx, thirdVertIdx.normalIdx, thirdVertIdx.uv0Idx, + secondVertIdx.vertIdx, secondVertIdx.normalIdx, secondVertIdx.uv0Idx, + firstVertIdx.vertIdx, firstVertIdx.normalIdx, firstVertIdx.uv0Idx); + + TiXmlText* triangleText = new TiXmlText(tri); + polyNode->LinkEndChild(triangleText); + } + } +} + void ColladaUtils::exportColladaMesh(TiXmlElement* rootNode, const OptimizedPolyList& mesh, const String& meshName, const Vector& matNames) { TiXmlElement* libGeomsNode = new TiXmlElement("library_geometries"); @@ -1576,6 +2105,380 @@ void ColladaUtils::exportColladaMesh(TiXmlElement* rootNode, const OptimizedPoly } +void ColladaUtils::exportColladaMesh(TiXmlElement* rootNode, const ExportData& exportData, const String& meshName) +{ + TiXmlElement* libGeomsNode = new TiXmlElement("library_geometries"); + rootNode->LinkEndChild(libGeomsNode); + + for (U32 d = 0; d < exportData.detailLevels.size(); d++) + { + char lodMeshName[256]; + dSprintf(lodMeshName, 256, "%s%d", meshName.c_str(), exportData.detailLevels[d].size); + + char lodMeshID[256]; + dSprintf(lodMeshID, 256, "%s-mesh", lodMeshName); + + TiXmlElement* geometryNode = new TiXmlElement("geometry"); + libGeomsNode->LinkEndChild(geometryNode); + geometryNode->SetAttribute("id", lodMeshID); + geometryNode->SetAttribute("name", lodMeshName); + + TiXmlElement* meshNode = new TiXmlElement("mesh"); + geometryNode->LinkEndChild(meshNode); + + // Save out the vertices + TiXmlElement* vertsSourceNode = new TiXmlElement("source"); + meshNode->LinkEndChild(vertsSourceNode); + vertsSourceNode->SetAttribute("id", avar("%s-mesh-positions", lodMeshName)); + + TiXmlElement* vertsNode = new TiXmlElement("float_array"); + vertsSourceNode->LinkEndChild(vertsNode); + vertsNode->SetAttribute("id", avar("%s-mesh-positions-array", lodMeshName)); + vertsNode->SetAttribute("count", avar("%d", exportData.detailLevels[d].mesh.mPoints.size() * 3)); + + for (U32 i = 0; i < exportData.detailLevels[d].mesh.mPoints.size(); i++) + { + const Point3F& vert = exportData.detailLevels[d].mesh.mPoints[i]; + + TiXmlText* vertText = new TiXmlText(avar("%.4f %.4f %.4f ", vert.x, vert.y, vert.z)); + vertsNode->LinkEndChild(vertText); + } + + // Save the vertex accessor + TiXmlElement* vertsTechNode = new TiXmlElement("technique_common"); + vertsSourceNode->LinkEndChild(vertsTechNode); + + TiXmlElement* vertsAccNode = new TiXmlElement("accessor"); + vertsTechNode->LinkEndChild(vertsAccNode); + vertsAccNode->SetAttribute("source", avar("#%s-mesh-positions-array", lodMeshName)); + vertsAccNode->SetAttribute("count", avar("%d", exportData.detailLevels[d].mesh.mPoints.size())); + vertsAccNode->SetAttribute("stride", "3"); + + TiXmlElement* vertsAccXNode = new TiXmlElement("param"); + vertsAccNode->LinkEndChild(vertsAccXNode); + vertsAccXNode->SetAttribute("name", "X"); + vertsAccXNode->SetAttribute("type", "float"); + + TiXmlElement* vertsAccYNode = new TiXmlElement("param"); + vertsAccNode->LinkEndChild(vertsAccYNode); + vertsAccYNode->SetAttribute("name", "Y"); + vertsAccYNode->SetAttribute("type", "float"); + + TiXmlElement* vertsAccZNode = new TiXmlElement("param"); + vertsAccNode->LinkEndChild(vertsAccZNode); + vertsAccZNode->SetAttribute("name", "Z"); + vertsAccZNode->SetAttribute("type", "float"); + + // Save out the normals + TiXmlElement* normalsSourceNode = new TiXmlElement("source"); + meshNode->LinkEndChild(normalsSourceNode); + normalsSourceNode->SetAttribute("id", avar("%s-mesh-normals", lodMeshName)); + + TiXmlElement* normalsNode = new TiXmlElement("float_array"); + normalsSourceNode->LinkEndChild(normalsNode); + normalsNode->SetAttribute("id", avar("%s-mesh-normals-array", lodMeshName)); + normalsNode->SetAttribute("count", avar("%d", exportData.detailLevels[d].mesh.mNormals.size() * 3)); + + for (U32 i = 0; i < exportData.detailLevels[d].mesh.mNormals.size(); i++) + { + const Point3F& normal = exportData.detailLevels[d].mesh.mNormals[i]; + + TiXmlText* normalText = new TiXmlText(avar("%.4f %.4f %.4f ", normal.x, normal.y, normal.z)); + normalsNode->LinkEndChild(normalText); + } + + // Save the normals accessor + TiXmlElement* normalsTechNode = new TiXmlElement("technique_common"); + normalsSourceNode->LinkEndChild(normalsTechNode); + + TiXmlElement* normalsAccNode = new TiXmlElement("accessor"); + normalsTechNode->LinkEndChild(normalsAccNode); + normalsAccNode->SetAttribute("source", avar("#%s-mesh-normals-array", lodMeshName)); + normalsAccNode->SetAttribute("count", avar("%d", exportData.detailLevels[d].mesh.mNormals.size())); + normalsAccNode->SetAttribute("stride", "3"); + + TiXmlElement* normalsAccXNode = new TiXmlElement("param"); + normalsAccNode->LinkEndChild(normalsAccXNode); + normalsAccXNode->SetAttribute("name", "X"); + normalsAccXNode->SetAttribute("type", "float"); + + TiXmlElement* normalsAccYNode = new TiXmlElement("param"); + normalsAccNode->LinkEndChild(normalsAccYNode); + normalsAccYNode->SetAttribute("name", "Y"); + normalsAccYNode->SetAttribute("type", "float"); + + TiXmlElement* normalsAccZNode = new TiXmlElement("param"); + normalsAccNode->LinkEndChild(normalsAccZNode); + normalsAccZNode->SetAttribute("name", "Z"); + normalsAccZNode->SetAttribute("type", "float"); + + // Save out the uvs + TiXmlElement* uv0SourceNode = new TiXmlElement("source"); + meshNode->LinkEndChild(uv0SourceNode); + uv0SourceNode->SetAttribute("id", avar("%s-mesh-map-0", lodMeshName)); + + TiXmlElement* uv0Node = new TiXmlElement("float_array"); + uv0SourceNode->LinkEndChild(uv0Node); + uv0Node->SetAttribute("id", avar("%s-mesh-map-0-array", lodMeshName)); + uv0Node->SetAttribute("count", avar("%d", exportData.detailLevels[d].mesh.mUV0s.size() * 2)); + + for (U32 i = 0; i < exportData.detailLevels[d].mesh.mUV0s.size(); i++) + { + const Point2F& uv0 = exportData.detailLevels[d].mesh.mUV0s[i]; + + TiXmlText* uv0Text = new TiXmlText(avar("%.4f %.4f ", uv0.x, 1.0f - uv0.y)); // COLLADA uvs are upside down compared to Torque + uv0Node->LinkEndChild(uv0Text); + } + + // Save the uv0 accessor + TiXmlElement* uv0TechNode = new TiXmlElement("technique_common"); + uv0SourceNode->LinkEndChild(uv0TechNode); + + TiXmlElement* uv0AccNode = new TiXmlElement("accessor"); + uv0TechNode->LinkEndChild(uv0AccNode); + uv0AccNode->SetAttribute("source", avar("#%s-mesh-map-0-array", lodMeshName)); + uv0AccNode->SetAttribute("count", avar("%d", exportData.detailLevels[d].mesh.mUV0s.size())); + uv0AccNode->SetAttribute("stride", "2"); + + TiXmlElement* uv0AccSNode = new TiXmlElement("param"); + uv0AccNode->LinkEndChild(uv0AccSNode); + uv0AccSNode->SetAttribute("name", "S"); + uv0AccSNode->SetAttribute("type", "float"); + + TiXmlElement* uv0AccTNode = new TiXmlElement("param"); + uv0AccNode->LinkEndChild(uv0AccTNode); + uv0AccTNode->SetAttribute("name", "T"); + uv0AccTNode->SetAttribute("type", "float"); + + // Define the vertices position array + TiXmlElement* verticesNode = new TiXmlElement("vertices"); + meshNode->LinkEndChild(verticesNode); + verticesNode->SetAttribute("id", avar("%s-mesh-vertices", lodMeshName)); + + TiXmlElement* verticesInputNode = new TiXmlElement("input"); + verticesNode->LinkEndChild(verticesInputNode); + verticesInputNode->SetAttribute("semantic", "POSITION"); + verticesInputNode->SetAttribute("source", avar("#%s-mesh-positions", lodMeshName)); + + Vector mapNames; + + //exportColladaTriangles(meshNode, exportData.detailLevels[d].mesh, lodMeshName, mapNames); + exportColladaTriangles(meshNode, exportData, d, lodMeshName); + + // Extra info useful for COLLADAMaya importer (OpenCOLLADA) + TiXmlElement* extraGeoNode = new TiXmlElement("extra"); + libGeomsNode->LinkEndChild(extraGeoNode); + + TiXmlElement* extraGeoNodeTech = new TiXmlElement("technique"); + extraGeoNode->LinkEndChild(extraGeoNodeTech); + extraGeoNodeTech->SetAttribute("profile", "OpenCOLLADAMaya"); + + TiXmlElement* mayaNode2Id = new TiXmlElement("originalMayaNodeId"); + extraGeoNodeTech->LinkEndChild(mayaNode2Id); + mayaNode2Id->SetAttribute("sid", "originalMayaNodeId"); + TiXmlText* mayaIdMesh = new TiXmlText(avar("%s", lodMeshName)); + mayaNode2Id->LinkEndChild(mayaIdMesh); + + TiXmlElement* doubleSidedId = new TiXmlElement("double_sided"); + extraGeoNodeTech->LinkEndChild(doubleSidedId); + doubleSidedId->SetAttribute("sid", "double_sided"); + TiXmlText* doubleSideIdText = new TiXmlText("1"); + doubleSidedId->LinkEndChild(doubleSideIdText); + + TiXmlElement* paramExtraNode = new TiXmlElement("param"); + extraGeoNodeTech->LinkEndChild(paramExtraNode); + paramExtraNode->SetAttribute("sid", "colladaId"); + paramExtraNode->SetAttribute("type", "string"); + + TiXmlText* mayaParamMesh = new TiXmlText(avar("%s-mesh", lodMeshName)); + paramExtraNode->LinkEndChild(mayaParamMesh); + } + + //And now collisions + for (U32 d = 0; d < exportData.colMeshes.size(); d++) + { + const char* colMeshName = exportData.colMeshes[d].colMeshName; + + char colMeshId[256]; + dSprintf(colMeshId, 256, "%s-mesh", colMeshName); + + TiXmlElement* geometryNode = new TiXmlElement("geometry"); + libGeomsNode->LinkEndChild(geometryNode); + geometryNode->SetAttribute("id", colMeshId); + geometryNode->SetAttribute("name", colMeshName); + + TiXmlElement* meshNode = new TiXmlElement("mesh"); + geometryNode->LinkEndChild(meshNode); + + // Save out the vertices + TiXmlElement* vertsSourceNode = new TiXmlElement("source"); + meshNode->LinkEndChild(vertsSourceNode); + vertsSourceNode->SetAttribute("id", avar("%s-mesh-positions", colMeshName)); + + TiXmlElement* vertsNode = new TiXmlElement("float_array"); + vertsSourceNode->LinkEndChild(vertsNode); + vertsNode->SetAttribute("id", avar("%s-mesh-positions-array", colMeshName)); + vertsNode->SetAttribute("count", avar("%d", exportData.colMeshes[d].mesh.mPoints.size() * 3)); + + for (U32 i = 0; i < exportData.colMeshes[d].mesh.mPoints.size(); i++) + { + const Point3F& vert = exportData.colMeshes[d].mesh.mPoints[i]; + + TiXmlText* vertText = new TiXmlText(avar("%.4f %.4f %.4f ", vert.x, vert.y, vert.z)); + vertsNode->LinkEndChild(vertText); + } + + // Save the vertex accessor + TiXmlElement* vertsTechNode = new TiXmlElement("technique_common"); + vertsSourceNode->LinkEndChild(vertsTechNode); + + TiXmlElement* vertsAccNode = new TiXmlElement("accessor"); + vertsTechNode->LinkEndChild(vertsAccNode); + vertsAccNode->SetAttribute("source", avar("#%s-mesh-positions-array", colMeshName)); + vertsAccNode->SetAttribute("count", avar("%d", exportData.colMeshes[d].mesh.mPoints.size())); + vertsAccNode->SetAttribute("stride", "3"); + + TiXmlElement* vertsAccXNode = new TiXmlElement("param"); + vertsAccNode->LinkEndChild(vertsAccXNode); + vertsAccXNode->SetAttribute("name", "X"); + vertsAccXNode->SetAttribute("type", "float"); + + TiXmlElement* vertsAccYNode = new TiXmlElement("param"); + vertsAccNode->LinkEndChild(vertsAccYNode); + vertsAccYNode->SetAttribute("name", "Y"); + vertsAccYNode->SetAttribute("type", "float"); + + TiXmlElement* vertsAccZNode = new TiXmlElement("param"); + vertsAccNode->LinkEndChild(vertsAccZNode); + vertsAccZNode->SetAttribute("name", "Z"); + vertsAccZNode->SetAttribute("type", "float"); + + // Save out the normals + TiXmlElement* normalsSourceNode = new TiXmlElement("source"); + meshNode->LinkEndChild(normalsSourceNode); + normalsSourceNode->SetAttribute("id", avar("%s-mesh-normals", colMeshName)); + + TiXmlElement* normalsNode = new TiXmlElement("float_array"); + normalsSourceNode->LinkEndChild(normalsNode); + normalsNode->SetAttribute("id", avar("%s-mesh-normals-array", colMeshName)); + normalsNode->SetAttribute("count", avar("%d", exportData.colMeshes[d].mesh.mNormals.size() * 3)); + + for (U32 i = 0; i < exportData.colMeshes[d].mesh.mNormals.size(); i++) + { + const Point3F& normal = exportData.colMeshes[d].mesh.mNormals[i]; + + TiXmlText* normalText = new TiXmlText(avar("%.4f %.4f %.4f ", normal.x, normal.y, normal.z)); + normalsNode->LinkEndChild(normalText); + } + + // Save the normals accessor + TiXmlElement* normalsTechNode = new TiXmlElement("technique_common"); + normalsSourceNode->LinkEndChild(normalsTechNode); + + TiXmlElement* normalsAccNode = new TiXmlElement("accessor"); + normalsTechNode->LinkEndChild(normalsAccNode); + normalsAccNode->SetAttribute("source", avar("#%s-mesh-normals-array", colMeshName)); + normalsAccNode->SetAttribute("count", avar("%d", exportData.colMeshes[d].mesh.mNormals.size())); + normalsAccNode->SetAttribute("stride", "3"); + + TiXmlElement* normalsAccXNode = new TiXmlElement("param"); + normalsAccNode->LinkEndChild(normalsAccXNode); + normalsAccXNode->SetAttribute("name", "X"); + normalsAccXNode->SetAttribute("type", "float"); + + TiXmlElement* normalsAccYNode = new TiXmlElement("param"); + normalsAccNode->LinkEndChild(normalsAccYNode); + normalsAccYNode->SetAttribute("name", "Y"); + normalsAccYNode->SetAttribute("type", "float"); + + TiXmlElement* normalsAccZNode = new TiXmlElement("param"); + normalsAccNode->LinkEndChild(normalsAccZNode); + normalsAccZNode->SetAttribute("name", "Z"); + normalsAccZNode->SetAttribute("type", "float"); + + // Save out the uvs + TiXmlElement* uv0SourceNode = new TiXmlElement("source"); + meshNode->LinkEndChild(uv0SourceNode); + uv0SourceNode->SetAttribute("id", avar("%s-mesh-map-0", colMeshName)); + + TiXmlElement* uv0Node = new TiXmlElement("float_array"); + uv0SourceNode->LinkEndChild(uv0Node); + uv0Node->SetAttribute("id", avar("%s-mesh-map-0-array", colMeshName)); + uv0Node->SetAttribute("count", avar("%d", exportData.colMeshes[d].mesh.mUV0s.size() * 2)); + + for (U32 i = 0; i < exportData.colMeshes[d].mesh.mUV0s.size(); i++) + { + const Point2F& uv0 = exportData.colMeshes[d].mesh.mUV0s[i]; + + TiXmlText* uv0Text = new TiXmlText(avar("%.4f %.4f ", uv0.x, 1.0f - uv0.y)); // COLLADA uvs are upside down compared to Torque + uv0Node->LinkEndChild(uv0Text); + } + + // Save the uv0 accessor + TiXmlElement* uv0TechNode = new TiXmlElement("technique_common"); + uv0SourceNode->LinkEndChild(uv0TechNode); + + TiXmlElement* uv0AccNode = new TiXmlElement("accessor"); + uv0TechNode->LinkEndChild(uv0AccNode); + uv0AccNode->SetAttribute("source", avar("#%s-mesh-map-0-array", colMeshName)); + uv0AccNode->SetAttribute("count", avar("%d", exportData.colMeshes[d].mesh.mUV0s.size())); + uv0AccNode->SetAttribute("stride", "2"); + + TiXmlElement* uv0AccSNode = new TiXmlElement("param"); + uv0AccNode->LinkEndChild(uv0AccSNode); + uv0AccSNode->SetAttribute("name", "S"); + uv0AccSNode->SetAttribute("type", "float"); + + TiXmlElement* uv0AccTNode = new TiXmlElement("param"); + uv0AccNode->LinkEndChild(uv0AccTNode); + uv0AccTNode->SetAttribute("name", "T"); + uv0AccTNode->SetAttribute("type", "float"); + + // Define the vertices position array + TiXmlElement* verticesNode = new TiXmlElement("vertices"); + meshNode->LinkEndChild(verticesNode); + verticesNode->SetAttribute("id", avar("%s-mesh-vertices", colMeshName)); + + TiXmlElement* verticesInputNode = new TiXmlElement("input"); + verticesNode->LinkEndChild(verticesInputNode); + verticesInputNode->SetAttribute("semantic", "POSITION"); + verticesInputNode->SetAttribute("source", avar("#%s-mesh-positions", colMeshName)); + + Vector mapNames; + + //exportColladaTriangles(meshNode, exportData.detailLevels[d].mesh, lodMeshName, mapNames); + exportColladaCollisionTriangles(meshNode, exportData, d); + + // Extra info useful for COLLADAMaya importer (OpenCOLLADA) + TiXmlElement* extraGeoNode = new TiXmlElement("extra"); + libGeomsNode->LinkEndChild(extraGeoNode); + + TiXmlElement* extraGeoNodeTech = new TiXmlElement("technique"); + extraGeoNode->LinkEndChild(extraGeoNodeTech); + extraGeoNodeTech->SetAttribute("profile", "OpenCOLLADAMaya"); + + TiXmlElement* mayaNode2Id = new TiXmlElement("originalMayaNodeId"); + extraGeoNodeTech->LinkEndChild(mayaNode2Id); + mayaNode2Id->SetAttribute("sid", "originalMayaNodeId"); + TiXmlText* mayaIdMesh = new TiXmlText(avar("%s", colMeshName)); + mayaNode2Id->LinkEndChild(mayaIdMesh); + + TiXmlElement* doubleSidedId = new TiXmlElement("double_sided"); + extraGeoNodeTech->LinkEndChild(doubleSidedId); + doubleSidedId->SetAttribute("sid", "double_sided"); + TiXmlText* doubleSideIdText = new TiXmlText("1"); + doubleSidedId->LinkEndChild(doubleSideIdText); + + TiXmlElement* paramExtraNode = new TiXmlElement("param"); + extraGeoNodeTech->LinkEndChild(paramExtraNode); + paramExtraNode->SetAttribute("sid", "colladaId"); + paramExtraNode->SetAttribute("type", "string"); + + TiXmlText* mayaParamMesh = new TiXmlText(avar("%s-mesh", colMeshName)); + paramExtraNode->LinkEndChild(mayaParamMesh); + } +} + void ColladaUtils::exportColladaScene(TiXmlElement* rootNode, const String& meshName, const Vector& matNames) { TiXmlElement* libSceneNode = new TiXmlElement("library_visual_scenes"); @@ -1695,6 +2598,244 @@ void ColladaUtils::exportColladaScene(TiXmlElement* rootNode, const String& mesh instVisSceneNode->SetAttribute("url", "#RootNode"); } +void ColladaUtils::exportColladaScene(TiXmlElement* rootNode, const ExportData& exportData, const String& meshName) +{ + TiXmlElement* libSceneNode = new TiXmlElement("library_visual_scenes"); + rootNode->LinkEndChild(libSceneNode); + + TiXmlElement* visSceneNode = new TiXmlElement("visual_scene"); + libSceneNode->LinkEndChild(visSceneNode); + visSceneNode->SetAttribute("id", "RootNode"); + visSceneNode->SetAttribute("name", "RootNode"); + + for (U32 d = 0; d < exportData.detailLevels.size(); d++) + { + char lodMeshName[256]; + dSprintf(lodMeshName, 256, "%s%d", meshName.c_str(), exportData.detailLevels[d].size); + + TiXmlElement* nodeNode = new TiXmlElement("node"); + visSceneNode->LinkEndChild(nodeNode); + nodeNode->SetAttribute("id", lodMeshName); + nodeNode->SetAttribute("name", lodMeshName); + nodeNode->SetAttribute("type", "NODE"); + + TiXmlElement* instanceGeomNode = new TiXmlElement("instance_geometry"); + nodeNode->LinkEndChild(instanceGeomNode); + instanceGeomNode->SetAttribute("url", avar("#%s%d-mesh", meshName.c_str(), exportData.detailLevels[d].size)); + instanceGeomNode->SetAttribute("name", lodMeshName); + + TiXmlElement* bindMatNode = new TiXmlElement("bind_material"); + instanceGeomNode->LinkEndChild(bindMatNode); + + TiXmlElement* techniqueNode = new TiXmlElement("technique_common"); + bindMatNode->LinkEndChild(techniqueNode); + + // Bind the materials + for (U32 i = 0; i < exportData.detailLevels[d].materialRefList.size(); i++) + { + int matIdx; + exportData.detailLevels[d].materialRefList.tryGetValue(i, matIdx); + BaseMatInstance* baseInst = exportData.materials[matIdx]; + + Material* mat = dynamic_cast(baseInst->getMaterial()); + if (!mat) + continue; + + String matName; + + if (mat->getName() && mat->getName()[0]) + matName = mat->mMapTo; + + TiXmlElement* instMatNode = new TiXmlElement("instance_material"); + techniqueNode->LinkEndChild(instMatNode); + instMatNode->SetAttribute("symbol", avar("%s-material", matName.c_str())); + instMatNode->SetAttribute("target", avar("#%s-material", matName.c_str())); + TiXmlElement* bindVertexNode = new TiXmlElement("bind_vertex_input"); + instMatNode->LinkEndChild(bindVertexNode); + //bindVertexNode->SetAttribute("semantic", avar("%s-mesh-map-0", meshName.c_str())); + bindVertexNode->SetAttribute("semantic", "UVMap"); + bindVertexNode->SetAttribute("input_semantic", "TEXCOORD"); + bindVertexNode->SetAttribute("input_set", "0"); + } + + // Extra info useful for COLLADAMax importer (OpenCOLLADA) + TiXmlElement* extraInsGeoNode = new TiXmlElement("extra"); + nodeNode->LinkEndChild(extraInsGeoNode); + + TiXmlElement* extraInsGeoTechNode = new TiXmlElement("technique"); + extraInsGeoNode->LinkEndChild(extraInsGeoTechNode); + extraInsGeoTechNode->SetAttribute("profile", "OpenCOLLADA"); + + TiXmlElement* castShadowsNode = new TiXmlElement("cast_shadows"); + extraInsGeoTechNode->LinkEndChild(castShadowsNode); + castShadowsNode->SetAttribute("sid", "cast_shadows"); + castShadowsNode->SetAttribute("type", "bool"); + + TiXmlText* castShadowsText = new TiXmlText("1"); + castShadowsNode->LinkEndChild(castShadowsText); + + //----------------------------- + TiXmlElement* receiveShadowsNode = new TiXmlElement("receive_shadows"); + extraInsGeoTechNode->LinkEndChild(receiveShadowsNode); + receiveShadowsNode->SetAttribute("sid", "receive_shadows"); + receiveShadowsNode->SetAttribute("type", "bool"); + + TiXmlText* receiveShadowsText = new TiXmlText("1"); + receiveShadowsNode->LinkEndChild(receiveShadowsText); + + //----------------------------- + TiXmlElement* primaryVisibiltyNode = new TiXmlElement("primary_visibility"); + extraInsGeoTechNode->LinkEndChild(primaryVisibiltyNode); + primaryVisibiltyNode->SetAttribute("sid", "primary_visibility"); + primaryVisibiltyNode->SetAttribute("type", "int"); + + TiXmlText* primaryVisibiltyText = new TiXmlText("1"); + primaryVisibiltyNode->LinkEndChild(primaryVisibiltyText); + + //----------------------------- + TiXmlElement* secondaryVisibilityNode = new TiXmlElement("secondary_visibility"); + extraInsGeoTechNode->LinkEndChild(secondaryVisibilityNode); + secondaryVisibilityNode->SetAttribute("sid", "secondary_visibility"); + secondaryVisibilityNode->SetAttribute("type", "int"); + + TiXmlText* secondaryVisibilityText = new TiXmlText("1"); + secondaryVisibilityNode->LinkEndChild(secondaryVisibilityText); + + // Extra info useful for COLLADAMaya importer (OpenCOLLADA) + TiXmlElement* extra2InsGeoNode = new TiXmlElement("extra"); + nodeNode->LinkEndChild(extra2InsGeoNode); + + TiXmlElement* extra2InsGeoTechNode = new TiXmlElement("technique"); + extra2InsGeoNode->LinkEndChild(extra2InsGeoTechNode); + extra2InsGeoTechNode->SetAttribute("profile", "OpenCOLLADAMaya"); + + TiXmlElement* mayaNodeId = new TiXmlElement("originalMayaNodeId"); + extra2InsGeoTechNode->LinkEndChild(mayaNodeId); + mayaNodeId->SetAttribute("sid", "originalMayaNodeId"); + mayaNodeId->SetAttribute("type", "string"); + + TiXmlText* mayaNodeIdMesh = new TiXmlText(lodMeshName); + mayaNodeId->LinkEndChild(mayaNodeIdMesh); + + TiXmlElement* paramExtraNode = new TiXmlElement("param"); + extra2InsGeoTechNode->LinkEndChild(paramExtraNode); + paramExtraNode->SetAttribute("sid", "colladaId"); + paramExtraNode->SetAttribute("type", "string"); + + TiXmlText* mayaParamMesh = new TiXmlText(lodMeshName); + paramExtraNode->LinkEndChild(mayaParamMesh); + } + + //Collisions + for (U32 d = 0; d < exportData.colMeshes.size(); d++) + { + const char* colMeshName = exportData.colMeshes[d].colMeshName; + + TiXmlElement* nodeNode = new TiXmlElement("node"); + visSceneNode->LinkEndChild(nodeNode); + nodeNode->SetAttribute("id", colMeshName); + nodeNode->SetAttribute("name", colMeshName); + nodeNode->SetAttribute("type", "NODE"); + + TiXmlElement* instanceGeomNode = new TiXmlElement("instance_geometry"); + nodeNode->LinkEndChild(instanceGeomNode); + instanceGeomNode->SetAttribute("url", avar("#%s-mesh", colMeshName)); + instanceGeomNode->SetAttribute("name", colMeshName); + + TiXmlElement* bindMatNode = new TiXmlElement("bind_material"); + instanceGeomNode->LinkEndChild(bindMatNode); + + TiXmlElement* techniqueNode = new TiXmlElement("technique_common"); + bindMatNode->LinkEndChild(techniqueNode); + + TiXmlElement* instMatNode = new TiXmlElement("instance_material"); + techniqueNode->LinkEndChild(instMatNode); + instMatNode->SetAttribute("symbol", avar("%s-material", colMeshName)); + instMatNode->SetAttribute("target", avar("#%s-material", colMeshName)); + TiXmlElement* bindVertexNode = new TiXmlElement("bind_vertex_input"); + instMatNode->LinkEndChild(bindVertexNode); + //bindVertexNode->SetAttribute("semantic", avar("%s-mesh-map-0", meshName.c_str())); + bindVertexNode->SetAttribute("semantic", "UVMap"); + bindVertexNode->SetAttribute("input_semantic", "TEXCOORD"); + bindVertexNode->SetAttribute("input_set", "0"); + + // Extra info useful for COLLADAMax importer (OpenCOLLADA) + TiXmlElement* extraInsGeoNode = new TiXmlElement("extra"); + nodeNode->LinkEndChild(extraInsGeoNode); + + TiXmlElement* extraInsGeoTechNode = new TiXmlElement("technique"); + extraInsGeoNode->LinkEndChild(extraInsGeoTechNode); + extraInsGeoTechNode->SetAttribute("profile", "OpenCOLLADA"); + + TiXmlElement* castShadowsNode = new TiXmlElement("cast_shadows"); + extraInsGeoTechNode->LinkEndChild(castShadowsNode); + castShadowsNode->SetAttribute("sid", "cast_shadows"); + castShadowsNode->SetAttribute("type", "bool"); + + TiXmlText* castShadowsText = new TiXmlText("1"); + castShadowsNode->LinkEndChild(castShadowsText); + + //----------------------------- + TiXmlElement* receiveShadowsNode = new TiXmlElement("receive_shadows"); + extraInsGeoTechNode->LinkEndChild(receiveShadowsNode); + receiveShadowsNode->SetAttribute("sid", "receive_shadows"); + receiveShadowsNode->SetAttribute("type", "bool"); + + TiXmlText* receiveShadowsText = new TiXmlText("1"); + receiveShadowsNode->LinkEndChild(receiveShadowsText); + + //----------------------------- + TiXmlElement* primaryVisibiltyNode = new TiXmlElement("primary_visibility"); + extraInsGeoTechNode->LinkEndChild(primaryVisibiltyNode); + primaryVisibiltyNode->SetAttribute("sid", "primary_visibility"); + primaryVisibiltyNode->SetAttribute("type", "int"); + + TiXmlText* primaryVisibiltyText = new TiXmlText("1"); + primaryVisibiltyNode->LinkEndChild(primaryVisibiltyText); + + //----------------------------- + TiXmlElement* secondaryVisibilityNode = new TiXmlElement("secondary_visibility"); + extraInsGeoTechNode->LinkEndChild(secondaryVisibilityNode); + secondaryVisibilityNode->SetAttribute("sid", "secondary_visibility"); + secondaryVisibilityNode->SetAttribute("type", "int"); + + TiXmlText* secondaryVisibilityText = new TiXmlText("1"); + secondaryVisibilityNode->LinkEndChild(secondaryVisibilityText); + + // Extra info useful for COLLADAMaya importer (OpenCOLLADA) + TiXmlElement* extra2InsGeoNode = new TiXmlElement("extra"); + nodeNode->LinkEndChild(extra2InsGeoNode); + + TiXmlElement* extra2InsGeoTechNode = new TiXmlElement("technique"); + extra2InsGeoNode->LinkEndChild(extra2InsGeoTechNode); + extra2InsGeoTechNode->SetAttribute("profile", "OpenCOLLADAMaya"); + + TiXmlElement* mayaNodeId = new TiXmlElement("originalMayaNodeId"); + extra2InsGeoTechNode->LinkEndChild(mayaNodeId); + mayaNodeId->SetAttribute("sid", "originalMayaNodeId"); + mayaNodeId->SetAttribute("type", "string"); + + TiXmlText* mayaNodeIdMesh = new TiXmlText(colMeshName); + mayaNodeId->LinkEndChild(mayaNodeIdMesh); + + TiXmlElement* paramExtraNode = new TiXmlElement("param"); + extra2InsGeoTechNode->LinkEndChild(paramExtraNode); + paramExtraNode->SetAttribute("sid", "colladaId"); + paramExtraNode->SetAttribute("type", "string"); + + TiXmlText* mayaParamMesh = new TiXmlText(colMeshName); + paramExtraNode->LinkEndChild(mayaParamMesh); + } + //----------------------------- + + TiXmlElement* sceneNode = new TiXmlElement("scene"); + rootNode->LinkEndChild(sceneNode); + + TiXmlElement* instVisSceneNode = new TiXmlElement("instance_visual_scene"); + sceneNode->LinkEndChild(instVisSceneNode); + instVisSceneNode->SetAttribute("url", "#RootNode"); +} + void ColladaUtils::exportToCollada(const Torque::Path& colladaFile, const OptimizedPolyList& mesh, const String& meshName) { // Get the mesh name @@ -1728,11 +2869,14 @@ void ColladaUtils::exportToCollada(const Torque::Path& colladaFile, const Optimi exportColladaMaterials(rootNode, mesh, mapNames, colladaFile); + S32 suffix; + String baseMeshName = String::GetTrailingNumber(outMeshName, suffix); + // Save out our geometry - exportColladaMesh(rootNode, mesh, outMeshName, mapNames); + exportColladaMesh(rootNode, mesh, baseMeshName, mapNames); // Save out our scene nodes - exportColladaScene(rootNode, outMeshName, mapNames); + exportColladaScene(rootNode, baseMeshName, mapNames); // Write out the actual Collada file char fullPath[MAX_PATH_LENGTH]; @@ -1740,4 +2884,139 @@ void ColladaUtils::exportToCollada(const Torque::Path& colladaFile, const Optimi if (!doc.SaveFile(fullPath)) Con::errorf("ColladaUtils::exportToCollada(): Unable to export to %s", fullPath); +} + +void ColladaUtils::exportToCollada(const Torque::Path& colladaFile, const ExportData& exportData) +{ + // Get the mesh name + String outMeshName = colladaFile.getFileName(); + + // The XML document that will hold all of our data + TiXmlDocument doc; + + // Add a standard XML declaration to the top + TiXmlDeclaration* xmlDecl = new TiXmlDeclaration("1.0", "utf-8", ""); + doc.LinkEndChild(xmlDecl); + + // Create our Collada root node and populate a couple standard attributes + TiXmlElement* rootNode = new TiXmlElement("COLLADA"); + rootNode->SetAttribute("xmlns", "http://www.collada.org/2005/11/COLLADASchema"); + rootNode->SetAttribute("version", "1.4.1"); + //rootNode->SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); //T3D Collada loader complaint about this. + + + // Add the root node to the document + doc.LinkEndChild(rootNode); + + // Save out our header info + exportColladaHeader(rootNode); + + // Save out the materials + Vector mapNames; + + exportColladaMaterials(rootNode, exportData, colladaFile); + + S32 suffix; + String baseMeshName = String::GetTrailingNumber(outMeshName, suffix); + + // Save out our geometry + exportColladaMesh(rootNode, exportData, baseMeshName); + + // Save out our scene nodes + exportColladaScene(rootNode, exportData, baseMeshName); + + // Write out the actual Collada file + char fullPath[MAX_PATH_LENGTH]; + Platform::makeFullPathName(colladaFile.getFullPath(), fullPath, MAX_PATH_LENGTH); + + if (!doc.SaveFile(fullPath)) + Con::errorf("ColladaUtils::exportToCollada(): Unable to export to %s", fullPath); +} + +void ColladaUtils::ExportData::processData() +{ + //This pref dictates if we 'backfill' lower LODs with higher ones if any given mesh being exported lacks that level. + //For example, if there are 2 meshes, and one has 500, 200, 100 and the other has 500 and 200 - if this setting is on, the second mesh + //will backfill the 200 to the 100 so it has all levels filled. If it's off, the second mesh will not render at the 100 level + bool fillLowDetailLevels = dAtob(Con::getVariable("$exportMesh::fillLowDetailLevels", "1")); + + S32 numDetailLevels = numberOfDetailLevels(); + + detailLevels.clear(); + detailLevels.setSize(numDetailLevels); + + for (U32 m = 0; m < meshData.size(); ++m) + { + for (U32 i = 0; i < numDetailLevels; ++i) + { + //Get our target size + S32 targetDetailLevelSize = getDetailLevelSize(i); + + //alright, step through each meshdata and propagate the polyList info 'up' to fill + detailLevel* curDetail = &detailLevels[i]; + + curDetail->size = targetDetailLevelSize; + + //Do we have a detail level for this? + S32 detailLevelIdx = -1; + + for (S32 mdl = i; mdl >= 0; mdl--) + { + //walk backwards as needed to find our first valid detail level for this mesh. if we find none, just move on + S32 testDetailLevelSize = getDetailLevelSize(mdl); + detailLevelIdx = meshData[m].hasDetailLevel(testDetailLevelSize); + + if (detailLevelIdx != -1) + break; + } + + if (detailLevelIdx == -1) + { + //found nothing backwards, so lets check if we're configured to back-fill the first detail levels + if (fillLowDetailLevels) + { + //if so, search forward, find the first valid detail and fill it in + for (S32 mdl = 0; mdl < numDetailLevels; mdl++) + { + //walk backwards as needed to find our first valid detail level for this mesh. if we find none, just move on + S32 testDetailLevelSize = getDetailLevelSize(mdl); + detailLevelIdx = meshData[m].hasDetailLevel(testDetailLevelSize); + + if (detailLevelIdx != -1) + break; + } + } + } + + //If we found the detail level index, go ahead and build out the data for it + if (detailLevelIdx != -1) + { + curDetail->mesh.setTransform(&meshData[m].meshTransform, meshData[m].scale); + curDetail->mesh.setObject(meshData[m].originatingObject); + + if (!meshData[m].shapeInst->buildPolyList(&curDetail->mesh, detailLevelIdx)) + { + Con::errorf("TSStatic::buildExportPolyList - failed to build polylist for LOD %i", i); + continue; + } + + //lastly, get material + for (U32 m = 0; m < curDetail->mesh.mMaterialList.size(); m++) + { + S32 matIdx = hasMaterialInstance(curDetail->mesh.mMaterialList[m]); + + if (matIdx == -1) + { + //cool, haven't already got this material, so lets store it out + materials.push_back(curDetail->mesh.mMaterialList[m]); + curDetail->materialRefList.insert(m, materials.size() - 1); + } + else + { + curDetail->materialRefList.insert(m, matIdx); + } + } + } + } + } } \ No newline at end of file diff --git a/Engine/source/ts/collada/colladaUtils.h b/Engine/source/ts/collada/colladaUtils.h index 04592126e..4997a8803 100644 --- a/Engine/source/ts/collada/colladaUtils.h +++ b/Engine/source/ts/collada/colladaUtils.h @@ -50,6 +50,10 @@ #include "console/console.h" #endif +#ifndef _TSSHAPEINSTANCE_H_ +#include "ts/tsShapeInstance.h" +#endif + #include "platform/tmm_off.h" #include "dae.h" @@ -63,6 +67,7 @@ #include "dom/domCOLLADA.h" #include "platform/tmm_on.h" +#include "core/strings/findMatch.h" namespace ColladaUtils { @@ -100,7 +105,7 @@ namespace ColladaUtils { upAxis = UPAXISTYPE_COUNT; unit = -1.0f; - lodType = DetectDTS; + lodType = TrailingNumber; singleDetailSize = 2; matNamePrefix = ""; alwaysImport = ""; @@ -117,6 +122,123 @@ namespace ColladaUtils ImportOptions& getOptions(); + struct ExportData + { + struct detailLevel + { + OptimizedPolyList mesh; + S32 size; + Map materialRefList; + }; + + struct meshLODData + { + Vector meshDetailLevels; + TSShapeInstance* shapeInst; + MatrixF meshTransform; + SceneObject* originatingObject; + + Point3F scale; + + S32 hasDetailLevel(S32 size) + { + for (U32 i = 0; i < meshDetailLevels.size(); ++i) + { + U32 mdlSize = meshDetailLevels[i].size; + + if (mdlSize == size) + return i; + } + + return -1; + } + }; + + struct colMesh + { + OptimizedPolyList mesh; + String colMeshName; + }; + + Vector detailLevels; + Vector meshData; + Vector colMeshes; + Vector materials; + + void processData(); + + S32 hasDetailLevel(U32 dl) + { + for (U32 i = 0; i < detailLevels.size(); i++) + { + if (detailLevels[i].size == dl) + return i; + } + + return -1; + } + + S32 hasMaterialInstance(BaseMatInstance* matInst) + { + for (U32 i = 0; i < materials.size(); i++) + { + if (materials[i] == matInst) + return i; + } + + return -1; + } + + S32 numberOfDetailLevels() + { + Vector detailLevelIdxs; + + for (U32 i = 0; i < meshData.size(); ++i) + { + for (U32 d = 0; d < meshData[i].meshDetailLevels.size(); ++d) + { + detailLevelIdxs.push_back_unique(meshData[i].meshDetailLevels[d].size); + } + } + + return detailLevelIdxs.size(); + } + + static S32 _Sort(const S32 *p1, const S32 *p2) + { + S32 e1 = (*p1); + S32 e2 = (*p2); + + if (e1 > e2) + return 1; + else if (e1 < e2) + return -1; + + return 0; + } + + S32 getDetailLevelSize(U32 detailIdx) + { + Vector detailLevelIdxs; + + for (U32 i = 0; i < meshData.size(); ++i) + { + for (U32 d = 0; d < meshData[i].meshDetailLevels.size(); ++d) + { + S32 mdlSize = meshData[i].meshDetailLevels[d].size; + detailLevelIdxs.push_back_unique(mdlSize); + } + } + + if (detailIdx >= detailLevelIdxs.size()) + return -1; + + detailLevelIdxs.sort(&_Sort); + + return detailLevelIdxs[detailIdx]; + } + }; + void convertTransform(MatrixF& m); void collapsePath(std::string& path); @@ -139,8 +261,15 @@ namespace ColladaUtils void exportColladaMesh(TiXmlElement* rootNode, const OptimizedPolyList& mesh, const String& meshName, const Vector& matNames); void exportColladaScene(TiXmlElement* rootNode, const String& meshName, const Vector& matNames); + void exportColladaMaterials(TiXmlElement* rootNode, const ExportData& exportData, const Torque::Path& colladaFile); + void exportColladaMesh(TiXmlElement* rootNode, const ExportData& exportData, const String& meshName); + void exportColladaCollisionTriangles(TiXmlElement* meshNode, const ExportData& exportData, const U32 collisionIdx); + void exportColladaTriangles(TiXmlElement* meshNode, const ExportData& exportData, const U32 detailLevel, const String& meshName); + void exportColladaScene(TiXmlElement* rootNode, const ExportData& exportData, const String& meshName); + // Export an OptimizedPolyList to a simple Collada file void exportToCollada(const Torque::Path& colladaFile, const OptimizedPolyList& mesh, const String& meshName = String::EmptyString); + void exportToCollada(const Torque::Path& colladaFile, const ExportData& exportData); }; //----------------------------------------------------------------------------- @@ -535,7 +664,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTrian continue; domUint* pSrcData = &(P->getValue()[0]); - S32 numTriangles = (P->getValue().getCount() / stride) - 2; + size_t numTriangles = (P->getValue().getCount() / stride) - 2; // Convert the strip back to a triangle list domUint* v0 = pSrcData; @@ -576,7 +705,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTriangl continue; domUint* pSrcData = &(P->getValue()[0]); - S32 numTriangles = (P->getValue().getCount() / stride) - 2; + size_t numTriangles = (P->getValue().getCount() / stride) - 2; // Convert the fan back to a triangle list domUint* v0 = pSrcData + stride; @@ -608,7 +737,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTriang continue; domUint* pSrcData = &(P->getValue()[0]); - S32 numPoints = P->getValue().getCount() / stride; + size_t numPoints = P->getValue().getCount() / stride; // Use a simple tri-fan (centered at the first point) method of // converting the polygon to triangles. diff --git a/Engine/source/ts/tsShapeConstruct.cpp b/Engine/source/ts/tsShapeConstruct.cpp index dd2a67644..fc5465401 100644 --- a/Engine/source/ts/tsShapeConstruct.cpp +++ b/Engine/source/ts/tsShapeConstruct.cpp @@ -135,6 +135,20 @@ IMPLEMENT_CONOBJECT(TSShapeConstructor); TSShapeConstructor::TSShapeConstructor() : mShapePath(""), mLoadingShape(false) { + mOptions.upAxis = UPAXISTYPE_COUNT; + mOptions.unit = -1.0f; + mOptions.lodType = ColladaUtils::ImportOptions::TrailingNumber; + mOptions.singleDetailSize = 2; + mOptions.matNamePrefix = ""; + mOptions.alwaysImport = ""; + mOptions.neverImport = String(Con::getVariable("$TSShapeConstructor::neverImport")); + mOptions.alwaysImportMesh = ""; + mOptions.neverImportMesh = String(Con::getVariable("$TSShapeConstructor::neverImportMesh")); + mOptions.ignoreNodeScale = false; + mOptions.adjustCenter = false; + mOptions.adjustFloor = false; + mOptions.forceUpdateMaterials = false; + mOptions.useDiffuseNames = false; mShape = NULL; } From 787b8be82c1a5d6183308596c8ae865a6f858092 Mon Sep 17 00:00:00 2001 From: Areloch Date: Sun, 4 Mar 2018 15:10:44 -0600 Subject: [PATCH 10/26] Adds handling for the proper updated exporting of mesh for convexShapes --- Engine/source/T3D/convexShape.cpp | 51 +++++++++++++++++++++++ Engine/source/T3D/convexShape.h | 1 + Engine/source/ts/collada/colladaUtils.cpp | 26 ++++++++++-- Engine/source/ts/collada/colladaUtils.h | 5 +++ 4 files changed, 80 insertions(+), 3 deletions(-) diff --git a/Engine/source/T3D/convexShape.cpp b/Engine/source/T3D/convexShape.cpp index b5134be65..ceaa75616 100644 --- a/Engine/source/T3D/convexShape.cpp +++ b/Engine/source/T3D/convexShape.cpp @@ -697,6 +697,57 @@ bool ConvexShape::buildPolyList( PolyListContext context, AbstractPolyList *plis return true; } +bool ConvexShape::buildExportPolyList(PolyListContext context, 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(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->fillWithSingleDetail = true; + + meshData->meshDetailLevels.increment(); + + ColladaUtils::ExportData::detailLevel* curDetail = &meshData->meshDetailLevels.last(); + + //Make sure we denote the size this detail level has + curDetail->size = getNextPow2(getObjBox().len()); + + bool t = true; + } + + return true; +} + void ConvexShape::_export( OptimizedPolyList *plist, const Box3F &box, const SphereF &sphere ) { BaseMatInstance *matInst = mMaterialInst; diff --git a/Engine/source/T3D/convexShape.h b/Engine/source/T3D/convexShape.h index d0f30eeaa..32d0122f5 100644 --- a/Engine/source/T3D/convexShape.h +++ b/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(PolyListContext context, 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 ); diff --git a/Engine/source/ts/collada/colladaUtils.cpp b/Engine/source/ts/collada/colladaUtils.cpp index 32c559077..8ad5bff9b 100644 --- a/Engine/source/ts/collada/colladaUtils.cpp +++ b/Engine/source/ts/collada/colladaUtils.cpp @@ -26,6 +26,9 @@ #include "ts/collada/colladaUtils.h" #include "materials/matInstance.h" +//special handling for export classes +#include "T3D/convexShape.h" + using namespace ColladaUtils; #define MAX_PATH_LENGTH 256 @@ -2994,10 +2997,27 @@ void ColladaUtils::ExportData::processData() curDetail->mesh.setTransform(&meshData[m].meshTransform, meshData[m].scale); curDetail->mesh.setObject(meshData[m].originatingObject); - if (!meshData[m].shapeInst->buildPolyList(&curDetail->mesh, detailLevelIdx)) + if (meshData[m].shapeInst != nullptr) { - Con::errorf("TSStatic::buildExportPolyList - failed to build polylist for LOD %i", i); - continue; + + if (!meshData[m].shapeInst->buildPolyList(&curDetail->mesh, detailLevelIdx)) + { + Con::errorf("TSStatic::buildExportPolyList - failed to build polylist for LOD %i", i); + continue; + } + } + else + { + //special handling classes + ConvexShape* convexShp = dynamic_cast(meshData[m].originatingObject); + if (convexShp != nullptr) + { + if (!convexShp->buildPolyList(PLC_Export, &curDetail->mesh, meshData[m].originatingObject->getWorldBox(), meshData[m].originatingObject->getWorldSphere())) + { + Con::errorf("TSStatic::buildExportPolyList - failed to build ConvexShape polylist for LOD %i", i); + continue; + } + } } //lastly, get material diff --git a/Engine/source/ts/collada/colladaUtils.h b/Engine/source/ts/collada/colladaUtils.h index 4997a8803..62a453ed3 100644 --- a/Engine/source/ts/collada/colladaUtils.h +++ b/Engine/source/ts/collada/colladaUtils.h @@ -140,6 +140,8 @@ namespace ColladaUtils Point3F scale; + bool fillWithSingleDetail; + S32 hasDetailLevel(S32 size) { for (U32 i = 0; i < meshDetailLevels.size(); ++i) @@ -152,6 +154,9 @@ namespace ColladaUtils return -1; } + + meshLODData() : shapeInst(nullptr), meshTransform(true), originatingObject(nullptr), scale(0), fillWithSingleDetail(false) + {} }; struct colMesh From 8dedcf456abb18932dab7207d60361ef07f09d73 Mon Sep 17 00:00:00 2001 From: Areloch Date: Sun, 4 Mar 2018 16:03:39 -0600 Subject: [PATCH 11/26] Cleanup of export function to remove redundant arg Removed unused var Cleaned up collision export on convexShape Added prefab export functionality --- Engine/source/T3D/convexShape.cpp | 6 ++---- Engine/source/T3D/convexShape.h | 2 +- Engine/source/T3D/prefab.cpp | 13 +++++++++++++ Engine/source/T3D/prefab.h | 2 ++ Engine/source/T3D/tsStatic.cpp | 2 +- Engine/source/T3D/tsStatic.h | 2 +- Engine/source/gui/worldEditor/worldEditor.cpp | 2 +- Engine/source/scene/sceneObject.h | 3 +-- Engine/source/ts/collada/colladaUtils.h | 4 +--- 9 files changed, 23 insertions(+), 13 deletions(-) diff --git a/Engine/source/T3D/convexShape.cpp b/Engine/source/T3D/convexShape.cpp index ceaa75616..d73d387bd 100644 --- a/Engine/source/T3D/convexShape.cpp +++ b/Engine/source/T3D/convexShape.cpp @@ -697,7 +697,7 @@ bool ConvexShape::buildPolyList( PolyListContext context, AbstractPolyList *plis return true; } -bool ConvexShape::buildExportPolyList(PolyListContext context, ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &) +bool ConvexShape::buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &) { if (mGeometry.points.empty()) return false; @@ -740,9 +740,7 @@ bool ConvexShape::buildExportPolyList(PolyListContext context, ColladaUtils::Exp ColladaUtils::ExportData::detailLevel* curDetail = &meshData->meshDetailLevels.last(); //Make sure we denote the size this detail level has - curDetail->size = getNextPow2(getObjBox().len()); - - bool t = true; + curDetail->size = 512; } return true; diff --git a/Engine/source/T3D/convexShape.h b/Engine/source/T3D/convexShape.h index 32d0122f5..413877a36 100644 --- a/Engine/source/T3D/convexShape.h +++ b/Engine/source/T3D/convexShape.h @@ -172,7 +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(PolyListContext context, ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &); + 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 ); diff --git a/Engine/source/T3D/prefab.cpp b/Engine/source/T3D/prefab.cpp index 6d357565f..a30a24217 100644 --- a/Engine/source/T3D/prefab.cpp +++ b/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 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" ) { diff --git a/Engine/source/T3D/prefab.h b/Engine/source/T3D/prefab.h index 48d87c232..fd1ebc2a4 100644 --- a/Engine/source/T3D/prefab.h +++ b/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 ); diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 9eaab881b..68b5333df 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -1073,7 +1073,7 @@ bool TSStatic::buildPolyList(PolyListContext context, AbstractPolyList* polyList return true; } -bool TSStatic::buildExportPolyList(PolyListContext context, ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &) +bool TSStatic::buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &) { if (!mShapeInstance) return false; diff --git a/Engine/source/T3D/tsStatic.h b/Engine/source/T3D/tsStatic.h index 2df45a861..9c6918c8d 100644 --- a/Engine/source/T3D/tsStatic.h +++ b/Engine/source/T3D/tsStatic.h @@ -138,7 +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(PolyListContext context, ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &); + bool buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &); void buildConvex(const Box3F& box, Convex* convex); bool _createShape(); diff --git a/Engine/source/gui/worldEditor/worldEditor.cpp b/Engine/source/gui/worldEditor/worldEditor.cpp index ca6c966ae..b66ead790 100644 --- a/Engine/source/gui/worldEditor/worldEditor.cpp +++ b/Engine/source/gui/worldEditor/worldEditor.cpp @@ -3932,7 +3932,7 @@ void WorldEditor::makeSelectionAMesh(const char *filename) for (S32 i = 0; i < objectList.size(); i++) { SceneObject *pObj = objectList[i]; - if (!pObj->buildExportPolyList(PLC_Export, &exportData, pObj->getWorldBox(), pObj->getWorldSphere())) + if (!pObj->buildExportPolyList(&exportData, pObj->getWorldBox(), pObj->getWorldSphere())) Con::warnf("colladaExportObjectList() - object %i returned no geometry.", pObj->getId()); } diff --git a/Engine/source/scene/sceneObject.h b/Engine/source/scene/sceneObject.h index 3e7fab355..34060acce 100644 --- a/Engine/source/scene/sceneObject.h +++ b/Engine/source/scene/sceneObject.h @@ -564,8 +564,7 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce /// @param box Box bounding volume /// @param sphere Sphere bounding volume /// - virtual bool buildExportPolyList(PolyListContext context, - ColladaUtils::ExportData *exportData, + virtual bool buildExportPolyList(ColladaUtils::ExportData *exportData, const Box3F& box, const SphereF& sphere) { return false; diff --git a/Engine/source/ts/collada/colladaUtils.h b/Engine/source/ts/collada/colladaUtils.h index 62a453ed3..144a62c7b 100644 --- a/Engine/source/ts/collada/colladaUtils.h +++ b/Engine/source/ts/collada/colladaUtils.h @@ -140,8 +140,6 @@ namespace ColladaUtils Point3F scale; - bool fillWithSingleDetail; - S32 hasDetailLevel(S32 size) { for (U32 i = 0; i < meshDetailLevels.size(); ++i) @@ -155,7 +153,7 @@ namespace ColladaUtils return -1; } - meshLODData() : shapeInst(nullptr), meshTransform(true), originatingObject(nullptr), scale(0), fillWithSingleDetail(false) + meshLODData() : shapeInst(nullptr), meshTransform(true), originatingObject(nullptr), scale(0) {} }; From 53f35e7fb1ce747336af1014f7c852d2ec9b4d2f Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Mon, 5 Mar 2018 23:48:09 -0500 Subject: [PATCH 12/26] Removed unused macString.mm that has old versions of string functions with no bounds checking --- Engine/source/platformMac/macString.mm | 69 -------------------------- 1 file changed, 69 deletions(-) delete mode 100644 Engine/source/platformMac/macString.mm diff --git a/Engine/source/platformMac/macString.mm b/Engine/source/platformMac/macString.mm deleted file mode 100644 index 3a255d924..000000000 --- a/Engine/source/platformMac/macString.mm +++ /dev/null @@ -1,69 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#import "platform/platform.h" -#import -#import -#import -#import -#import -#import "core/strings/stringFunctions.h" - -char *dStrnew(const char *src) -{ - char *buffer = new char[dStrlen(src) + 1]; - dStrcpy(buffer, src); - return buffer; -} - -char* dStrstr(char *str1, char *str2) -{ - return strstr(str1,str2); -} - -int dSprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, ...) -{ - va_list args; - va_start(args, format); - S32 len = vsprintf(buffer, format, args); - va_end(args); - return (len); -} - - -int dVsprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, va_list arglist) -{ - S32 len = vsprintf(buffer, format, arglist); - - return (len); -} - -int dFflushStdout() -{ - return fflush(stdout); -} - -int dFflushStderr() -{ - return fflush(stderr); -} - From 7769da9434ab7f3ccbac40daf7d34d4f02444594 Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Tue, 6 Mar 2018 00:48:44 -0500 Subject: [PATCH 13/26] Use strncat instead of strcat to prevent some buffer overflows --- Engine/source/T3D/shapeImage.cpp | 2 +- Engine/source/afx/arcaneFX.cpp | 6 +- Engine/source/afx/rpg/afxRPGMagicSpell.cpp | 2 +- Engine/source/app/net/net.cpp | 4 +- Engine/source/console/codeInterpreter.cpp | 22 +++--- Engine/source/console/compiledEval.cpp | 4 +- Engine/source/console/console.cpp | 4 +- Engine/source/console/consoleFunctions.cpp | 6 +- Engine/source/console/consoleInternal.cpp | 18 ++--- Engine/source/console/consoleObject.cpp | 12 +-- Engine/source/console/fieldBrushObject.cpp | 2 +- Engine/source/console/persistenceManager.cpp | 8 +- Engine/source/console/scriptFilename.cpp | 2 +- Engine/source/console/simFieldDictionary.cpp | 2 +- Engine/source/console/simObject.cpp | 12 +-- Engine/source/console/telnetDebugger.cpp | 10 +-- Engine/source/core/strings/stringFunctions.h | 14 +++- Engine/source/core/strings/stringUnit.cpp | 6 +- Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp | 2 +- Engine/source/gui/containers/guiFormCtrl.cpp | 4 +- .../gui/controls/guiDirectoryFileListCtrl.cpp | 2 +- Engine/source/gui/controls/guiListBoxCtrl.cpp | 2 +- Engine/source/gui/editor/guiFilterCtrl.cpp | 4 +- .../source/gui/worldEditor/terrainEditor.cpp | 8 +- .../source/materials/materialDefinition.cpp | 10 +-- Engine/source/platform/profiler.cpp | 4 +- Engine/source/platformPOSIX/posixVolume.cpp | 2 +- .../source/platformWin32/winDInputDevice.cpp | 14 ++-- Engine/source/platformWin32/winFileio.cpp | 9 ++- Engine/source/sim/actionMap.cpp | 78 +++++++++---------- Engine/source/sim/netStringTable.cpp | 2 +- Engine/source/terrain/terrData.cpp | 4 +- 32 files changed, 147 insertions(+), 134 deletions(-) diff --git a/Engine/source/T3D/shapeImage.cpp b/Engine/source/T3D/shapeImage.cpp index 627e8e433..4319baa4e 100644 --- a/Engine/source/T3D/shapeImage.cpp +++ b/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) diff --git a/Engine/source/afx/arcaneFX.cpp b/Engine/source/afx/arcaneFX.cpp index 59da040ea..8ec0e9760 100644 --- a/Engine/source/afx/arcaneFX.cpp +++ b/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); 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); 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); Con::errorf("%s -- [%s]", ret, argv[1].getStringValue()); ret[0] = 0; diff --git a/Engine/source/afx/rpg/afxRPGMagicSpell.cpp b/Engine/source/afx/rpg/afxRPGMagicSpell.cpp index dae982fa8..6490ad260 100644 --- a/Engine/source/afx/rpg/afxRPGMagicSpell.cpp +++ b/Engine/source/afx/rpg/afxRPGMagicSpell.cpp @@ -227,7 +227,7 @@ char* afxRPGMagicSpellData::formatDesc(char* buffer, int len) const { dStrcpy(target_str, _afxRPGMagicSpell_TargetType::_sEnumTable[i].mName); if (spell_target != TARGET_FREE && target_optional) - dStrcat(target_str, " (opt)"); + dStrcat(target_str, " (opt)", 32); } break; } diff --git a/Engine/source/app/net/net.cpp b/Engine/source/app/net/net.cpp index ab08da057..f668d2651 100644 --- a/Engine/source/app/net/net.cpp +++ b/Engine/source/app/net/net.cpp @@ -129,7 +129,7 @@ if(conn->isConnectionToServer()) { dStrcpy(mBuf, "clientCmd"); - dStrcat(mBuf, rmtCommandName); + dStrcat(mBuf, rmtCommandName, 1024); char *temp = mArgv[1]; mArgv[1] = mBuf; @@ -140,7 +140,7 @@ else { dStrcpy(mBuf, "serverCmd"); - dStrcat(mBuf, rmtCommandName); + dStrcat(mBuf, rmtCommandName, 1024); char *temp = mArgv[1]; dSprintf(idBuf, sizeof(idBuf), "%d", conn->getId()); diff --git a/Engine/source/console/codeInterpreter.cpp b/Engine/source/console/codeInterpreter.cpp index a0e13502f..0b5986fda 100644 --- a/Engine/source/console/codeInterpreter.cpp +++ b/Engine/source/console/codeInterpreter.cpp @@ -420,13 +420,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 +471,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 +491,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); } diff --git a/Engine/source/console/compiledEval.cpp b/Engine/source/console/compiledEval.cpp index dc6f8a5f5..73969afb2 100644 --- a/Engine/source/console/compiledEval.cpp +++ b/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; } diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index c3779de63..ff204a448 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -2176,8 +2176,8 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor } // Format the output path. - dStrncat(pathBuffer, "/", sizeof(pathBuffer) - 1 - strlen(pathBuffer)); - dStrncat(pathBuffer, pSrc, sizeof(pathBuffer) - 1 - strlen(pathBuffer)); + dStrcat(pathBuffer, "/", sizeof(pathBuffer) - 1 - strlen(pathBuffer)); + dStrcat(pathBuffer, pSrc, sizeof(pathBuffer) - 1 - strlen(pathBuffer)); // Are we ensuring the trailing slash? if (ensureTrailingSlash) diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index df89a788a..16c20c3c3 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -1889,7 +1889,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); Con::printf("%s", ret); ret[0] = 0; @@ -1913,7 +1913,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); Con::warnf(ConsoleLogEntry::General, "%s", ret); ret[0] = 0; @@ -1937,7 +1937,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); Con::errorf(ConsoleLogEntry::General, "%s", ret); ret[0] = 0; diff --git a/Engine/source/console/consoleInternal.cpp b/Engine/source/console/consoleInternal.cpp index eadee5d7b..3f5c78f67 100644 --- a/Engine/source/console/consoleInternal.cpp +++ b/Engine/source/console/consoleInternal.cpp @@ -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); @@ -1362,7 +1362,7 @@ void Namespace::addScriptCallback(const char *funcName, const char *usage, Conso char lilBuffer[32]; dStrcpy(buffer, funcName); dSprintf(lilBuffer, 32, "_%d_cb", uid++); - dStrcat(buffer, lilBuffer); + dStrcat(buffer, lilBuffer, 1024); Entry *ent = createLocalEntry(StringTable->insert(buffer)); trashCache(); @@ -1383,7 +1383,7 @@ void Namespace::markGroup(const char* name, const char* usage) char lilBuffer[32]; dStrcpy(buffer, name); dSprintf(lilBuffer, 32, "_%d", uid++); - dStrcat(buffer, lilBuffer); + dStrcat(buffer, lilBuffer, 1024); Entry *ent = createLocalEntry(StringTable->insert(buffer)); trashCache(); diff --git a/Engine/source/console/consoleObject.cpp b/Engine/source/console/consoleObject.cpp index e1744c5e1..32c84f20b 100644 --- a/Engine/source/console/consoleObject.cpp +++ b/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; @@ -776,8 +776,8 @@ static const char* returnClassList( Vector< AbstractClassRep* >& classes, U32 bu dStrcpy( ret, classes[ 0 ]->getClassName() ); 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; diff --git a/Engine/source/console/fieldBrushObject.cpp b/Engine/source/console/fieldBrushObject.cpp index 407a57cb3..e96387cae 100644 --- a/Engine/source/console/fieldBrushObject.cpp +++ b/Engine/source/console/fieldBrushObject.cpp @@ -275,7 +275,7 @@ DefineConsoleMethod(FieldBrushObject, queryFields, const char*, (const char* sim // Copy string element. dStrcpy( tempBuf, StringUnit::getUnit( groupList, groupIndex, " \t\n" ) ); // Append internal name. - dStrcat( tempBuf, "_begingroup" ); + dStrcat( tempBuf, "_begingroup", 256 ); // Store Group. groups.push_back( StringTable->insert( tempBuf ) ); } diff --git a/Engine/source/console/persistenceManager.cpp b/Engine/source/console/persistenceManager.cpp index c4af549ed..db7b7254e 100644 --- a/Engine/source/console/persistenceManager.cpp +++ b/Engine/source/console/persistenceManager.cpp @@ -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); if ( newValue ) - dStrcat(newLine, newValue); - dStrcat(newLine, postString); + dStrcat(newLine, newValue, newLineLen); + dStrcat(newLine, postString, newLineLen); // 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"; diff --git a/Engine/source/console/scriptFilename.cpp b/Engine/source/console/scriptFilename.cpp index 7a72756af..9455826f7 100644 --- a/Engine/source/console/scriptFilename.cpp +++ b/Engine/source/console/scriptFilename.cpp @@ -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; } diff --git a/Engine/source/console/simFieldDictionary.cpp b/Engine/source/console/simFieldDictionary.cpp index f68a8689b..397b51d23 100644 --- a/Engine/source/console/simFieldDictionary.cpp +++ b/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); } diff --git a/Engine/source/console/simObject.cpp b/Engine/source/console/simObject.cpp index ef688228f..0d2e5eb32 100644 --- a/Engine/source/console/simObject.cpp +++ b/Engine/source/console/simObject.cpp @@ -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); @@ -1029,7 +1029,7 @@ void SimObject::setDataField(StringTableEntry slotName, const char *array, const { char buf[256]; dStrcpy(buf, slotName); - dStrcat(buf, array); + dStrcat(buf, array, 256); StringTableEntry permanentSlotName = StringTable->insert(buf); mFieldDictionary->setFieldValue(permanentSlotName, value); onDynamicModified( permanentSlotName, value ); @@ -1070,7 +1070,7 @@ const char *SimObject::getDataField(StringTableEntry slotName, const char *array { static char buf[256]; dStrcpy(buf, slotName); - dStrcat(buf, array); + dStrcat(buf, array, 256); if (const char* val = mFieldDictionary->getFieldValue(StringTable->insert(buf))) return val; } @@ -1311,7 +1311,7 @@ U32 SimObject::getDataFieldType( StringTableEntry slotName, const char* array ) { static char buf[256]; dStrcpy( buf, slotName ); - dStrcat( buf, array ); + dStrcat( buf, array, 256 ); return mFieldDictionary->getFieldType( StringTable->insert( buf ) ); } @@ -1334,7 +1334,7 @@ void SimObject::setDataFieldType(const U32 fieldTypeId, StringTableEntry slotNam { static char buf[256]; dStrcpy( buf, slotName ); - dStrcat( buf, array ); + dStrcat( buf, array, 256 ); mFieldDictionary->setFieldType( StringTable->insert( buf ), fieldTypeId ); onDynamicModified( slotName, mFieldDictionary->getFieldValue(slotName) ); @@ -1355,7 +1355,7 @@ void SimObject::setDataFieldType(const char *typeName, StringTableEntry slotName { static char buf[256]; dStrcpy( buf, slotName ); - dStrcat( buf, array ); + dStrcat( buf, array, 256 ); StringTableEntry permanentSlotName = StringTable->insert(buf); mFieldDictionary->setFieldType( permanentSlotName, typeName ); diff --git a/Engine/source/console/telnetDebugger.cpp b/Engine/source/console/telnetDebugger.cpp index 7db6e9710..7cb39dc83 100644 --- a/Engine/source/console/telnetDebugger.cpp +++ b/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 = ""; - dStrcat( scope, function ); + dStrcat( scope, function, MaxCommandSize ); U32 line=0, inst; U32 ip = gEvalState.stack[i]->ip; diff --git a/Engine/source/core/strings/stringFunctions.h b/Engine/source/core/strings/stringFunctions.h index 6a3d54548..4c79bf32d 100644 --- a/Engine/source/core/strings/stringFunctions.h +++ b/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 @@ -47,14 +51,22 @@ //------------------------------------------------------------------------------ // standard string functions [defined in platformString.cpp] +/// @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); } +inline char *dStrcat(char *dst, const char *src, dsize_t len) +{ + return strncat(dst,src,len - 1); //Safety because strncat copies at most len+1 characters +} + inline char *dStrncat(char *dst, const char *src, dsize_t len) { - return strncat(dst,src,len); + AssertFatal(false, "Use dStrcat with length"); + return dStrcat(dst, src, len); } inline S32 dStrcmp(const char *str1, const char *str2) diff --git a/Engine/source/core/strings/stringUnit.cpp b/Engine/source/core/strings/stringUnit.cpp index dc666f38c..0012d60e6 100644 --- a/Engine/source/core/strings/stringUnit.cpp +++ b/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; } } diff --git a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp index 3f3245c91..d909750b9 100644 --- a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp +++ b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp @@ -129,7 +129,7 @@ void GFXGLDevice::enumerateAdapters( Vector &adapterList ) if (renderer) { dStrcpy(toAdd->mName, renderer); - dStrncat(toAdd->mName, " OpenGL", GFXAdapter::MaxAdapterNameLen); + dStrcat(toAdd->mName, " OpenGL", GFXAdapter::MaxAdapterNameLen); } else dStrcpy(toAdd->mName, "OpenGL"); diff --git a/Engine/source/gui/containers/guiFormCtrl.cpp b/Engine/source/gui/containers/guiFormCtrl.cpp index f94e6c234..a185af1e2 100644 --- a/Engine/source/gui/containers/guiFormCtrl.cpp +++ b/Engine/source/gui/containers/guiFormCtrl.cpp @@ -219,8 +219,8 @@ bool GuiFormCtrl::resize(const Point2I &newPosition, const Point2I &newExtent) for(S32 i=strlen; i>=0; --i) { dStrcpy(buf, ""); - dStrncat(buf, (const char*)mCaption, i); - dStrcat(buf, "..."); + dStrcat(buf, (const char*)mCaption, i); + dStrcat(buf, "...", i); textWidth = mProfile->mFont->getStrWidth(buf); diff --git a/Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp b/Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp index c244af658..420ddc575 100644 --- a/Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp +++ b/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; diff --git a/Engine/source/gui/controls/guiListBoxCtrl.cpp b/Engine/source/gui/controls/guiListBoxCtrl.cpp index 8c0dabb11..d47914d3d 100644 --- a/Engine/source/gui/controls/guiListBoxCtrl.cpp +++ b/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; diff --git a/Engine/source/gui/editor/guiFilterCtrl.cpp b/Engine/source/gui/editor/guiFilterCtrl.cpp index a00d4f670..6b7662bd5 100644 --- a/Engine/source/gui/editor/guiFilterCtrl.cpp +++ b/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; diff --git a/Engine/source/gui/worldEditor/terrainEditor.cpp b/Engine/source/gui/worldEditor/terrainEditor.cpp index 59d8adaca..8e81d84e3 100644 --- a/Engine/source/gui/worldEditor/terrainEditor.cpp +++ b/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; diff --git a/Engine/source/materials/materialDefinition.cpp b/Engine/source/materials/materialDefinition.cpp index d4ec8ed7d..d116fe0f3 100644 --- a/Engine/source/materials/materialDefinition.cpp +++ b/Engine/source/materials/materialDefinition.cpp @@ -661,28 +661,28 @@ DefineConsoleMethod( Material, getAnimFlags, const char*, (U32 id), , "" ) if(dStrcmp( animFlags, "" ) == 0) dStrcpy( animFlags, "$Rotate" ); else - dStrcat( animFlags, " | $Rotate"); + dStrcat( animFlags, " | $Rotate", 512); } if(object->mAnimFlags[ id ] & Material::Wave) { if(dStrcmp( animFlags, "" ) == 0) dStrcpy( animFlags, "$Wave" ); else - dStrcat( animFlags, " | $Wave"); + dStrcat( animFlags, " | $Wave", 512); } if(object->mAnimFlags[ id ] & Material::Scale) { if(dStrcmp( animFlags, "" ) == 0) dStrcpy( animFlags, "$Scale" ); else - dStrcat( animFlags, " | $Scale"); + dStrcat( animFlags, " | $Scale", 512); } if(object->mAnimFlags[ id ] & Material::Sequence) { if(dStrcmp( animFlags, "" ) == 0) dStrcpy( animFlags, "$Sequence" ); 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; -} \ No newline at end of file +} diff --git a/Engine/source/platform/profiler.cpp b/Engine/source/platform/profiler.cpp index 444679284..e70eb6c02 100644 --- a/Engine/source/platform/profiler.cpp +++ b/Engine/source/platform/profiler.cpp @@ -329,8 +329,8 @@ const char * Profiler::constructProfilePath(ProfilerData * pd) U32 mark = FrameAllocator::getWaterMark(); char * buf = (char*)FrameAllocator::alloc(len+1); dStrcpy(buf,pd->mParent->mPath); - dStrcat(buf,connector); - dStrcat(buf,pd->mRoot->mName); + dStrcat(buf,connector,len); + dStrcat(buf,pd->mRoot->mName,len); const char * ret = StringTable->insert(buf); FrameAllocator::setWaterMark(mark); diff --git a/Engine/source/platformPOSIX/posixVolume.cpp b/Engine/source/platformPOSIX/posixVolume.cpp index 0f39bea3c..271df1e18 100644 --- a/Engine/source/platformPOSIX/posixVolume.cpp +++ b/Engine/source/platformPOSIX/posixVolume.cpp @@ -585,7 +585,7 @@ bool Platform::FS::InstallFileSystems() { // add trailing '/' if it isn't there if (buffer[dStrlen(buffer) - 1] != '/') - dStrcat(buffer, "/"); + dStrcat(buffer, "/", PATH_MAX); Platform::FS::SetCwd(buffer); } diff --git a/Engine/source/platformWin32/winDInputDevice.cpp b/Engine/source/platformWin32/winDInputDevice.cpp index a88f9ff1d..1bfed04f8 100644 --- a/Engine/source/platformWin32/winDInputDevice.cpp +++ b/Engine/source/platformWin32/winDInputDevice.cpp @@ -1552,25 +1552,25 @@ const char* DInputDevice::getJoystickAxesString() switch ( mObjInfo[i].mInst ) { case SI_XAXIS: - dStrcat( buf, "\tX" ); + dStrcat( buf, "\tX", 64 ); break; case SI_YAXIS: - dStrcat( buf, "\tY" ); + dStrcat( buf, "\tY", 64 ); break; case SI_ZAXIS: - dStrcat( buf, "\tZ" ); + dStrcat( buf, "\tZ", 64 ); break; case SI_RXAXIS: - dStrcat( buf, "\tR" ); + dStrcat( buf, "\tR", 64 ); break; case SI_RYAXIS: - dStrcat( buf, "\tU" ); + dStrcat( buf, "\tU", 64 ); break; case SI_RZAXIS: - dStrcat( buf, "\tV" ); + dStrcat( buf, "\tV", 64 ); break; case SI_SLIDER: - dStrcat( buf, "\tS" ); + dStrcat( buf, "\tS", 64 ); break; } } diff --git a/Engine/source/platformWin32/winFileio.cpp b/Engine/source/platformWin32/winFileio.cpp index 85f8676a3..1fba156f5 100644 --- a/Engine/source/platformWin32/winFileio.cpp +++ b/Engine/source/platformWin32/winFileio.cpp @@ -158,7 +158,8 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) Platform::clearExcludedDirectories(); - TempAlloc< char > tempBuf( to.size * 3 + MAX_PATH * 3 ); + S32 tempBufSize = to.size * 3 + MAX_PATH * 3; + TempAlloc< char > tempBuf( tempBufSize ); // Create all the directories. for (S32 i = 0; i < directoryInfo.size(); i++) @@ -168,7 +169,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) char* toDir = tempBuf; Platform::makeFullPathName(fromDir + dStrlen(fromName) + (dStricmp(fromDir, fromName) ? 1 : 0), tempBuf, tempBuf.size, toName); if(*(toDir + dStrlen(toDir) - 1) != '/') - dStrcat(toDir, "/"); + dStrcat(toDir, "/", tempBufSize); forwardslash(toDir); if (!Platform::createPath(toDir)) @@ -191,8 +192,8 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) char* toFile = tempBuf; Platform::makeFullPathName(fileInfo[i].pFullPath + dStrlen(fromName) + (dStricmp(fileInfo[i].pFullPath, fromName) ? 1 : 0), tempBuf, tempBuf.size, toName); - dStrcat(toFile, "/"); - dStrcat(toFile, fileInfo[i].pFileName); + dStrcat(toFile, "/", tempBufSize); + dStrcat(toFile, fileInfo[i].pFileName, tempBufSize); backslash(fromFile); backslash(toFile); diff --git a/Engine/source/sim/actionMap.cpp b/Engine/source/sim/actionMap.cpp index 841f3e39b..4e5f6948a 100644 --- a/Engine/source/sim/actionMap.cpp +++ b/Engine/source/sim/actionMap.cpp @@ -249,7 +249,7 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const iostrm->write( dStrlen( lineBuffer ), lineBuffer ); } - dSprintf(lineBuffer, 1023, "if (isObject(%s)) %s.delete();\n" + dSprintf(lineBuffer, 1024, "if (isObject(%s)) %s.delete();\n" "new ActionMap(%s);\n", getName(), getName(), getName()); iostrm->write(dStrlen(lineBuffer), lineBuffer); @@ -277,7 +277,7 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const else command = "bind"; - dSprintf(lineBuffer, 1023, "%s.%s(%s, \"%s%s\"", + dSprintf(lineBuffer, 1024, "%s.%s(%s, \"%s%s\"", getName(), command, devbuffer, @@ -298,53 +298,53 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const buff[curr++] = 'I'; buff[curr] = '\0'; - dStrcat(lineBuffer, buff); + dStrcat(lineBuffer, buff, 1024); } if (rNode.flags & Node::HasDeadZone) { char buff[64]; dSprintf(buff, 63, ", \"%g %g\"", rNode.deadZoneBegin, rNode.deadZoneEnd); - dStrcat(lineBuffer, buff); + dStrcat(lineBuffer, buff, 1024); } if (rNode.flags & Node::HasScale) { char buff[64]; dSprintf(buff, 63, ", %g", rNode.scaleFactor); - dStrcat(lineBuffer, buff); + dStrcat(lineBuffer, buff, 1024); } if (rNode.flags & Node::BindCmd) { if (rNode.makeConsoleCommand) { - dStrcat(lineBuffer, ", \""); + dStrcat(lineBuffer, ", \"", 1024); U32 pos = dStrlen(lineBuffer); expandEscape(lineBuffer + pos, rNode.makeConsoleCommand); - dStrcat(lineBuffer, "\""); + dStrcat(lineBuffer, "\"", 1024); } else { - dStrcat(lineBuffer, ", \"\""); + dStrcat(lineBuffer, ", \"\"", 1024); } if (rNode.breakConsoleCommand) { - dStrcat(lineBuffer, ", \""); + dStrcat(lineBuffer, ", \"", 1024); U32 pos = dStrlen(lineBuffer); expandEscape(lineBuffer + pos, rNode.breakConsoleCommand); - dStrcat(lineBuffer, "\""); + dStrcat(lineBuffer, "\"", 1024); } else - dStrcat(lineBuffer, ", \"\""); + dStrcat(lineBuffer, ", \"\"", 1024); } else if (rNode.flags & Node::Held) { - dStrcat(lineBuffer, ", "); - dStrcat(lineBuffer, rNode.consoleFunction); + dStrcat(lineBuffer, ", ", 1024); + dStrcat(lineBuffer, rNode.consoleFunction, 1024); - dStrcat(lineBuffer, ", "); - dStrcat(lineBuffer, rNode.contextEvent->mConsoleFunctionHeld); + dStrcat(lineBuffer, ", ", 1024); + dStrcat(lineBuffer, rNode.contextEvent->mConsoleFunctionHeld, 1024); } else { - dStrcat(lineBuffer, ", "); - dStrcat(lineBuffer, rNode.consoleFunction); + dStrcat(lineBuffer, ", ", 1024); + dStrcat(lineBuffer, rNode.consoleFunction, 1024); } - dStrcat(lineBuffer, ");\n"); + dStrcat(lineBuffer, ");\n", 1024); iostrm->write(dStrlen(lineBuffer), lineBuffer); } } @@ -377,7 +377,7 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const command = "bind"; char finalBuffer[1024]; - dSprintf(finalBuffer, 1023, "%s.%s(%s, \"%s%s\"", + dSprintf(finalBuffer, 1024, "%s.%s(%s, \"%s%s\"", getName(), command, devbuffer, @@ -398,51 +398,51 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const buff[curr++] = 'I'; buff[curr] = '\0'; - dStrcat(finalBuffer, buff); + dStrcat(finalBuffer, buff, 1024); } if (rNode.flags & Node::HasDeadZone) { char buff[64]; dSprintf(buff, 63, ", \"%g %g\"", rNode.deadZoneBegin, rNode.deadZoneEnd); - dStrcat(finalBuffer, buff); + dStrcat(finalBuffer, buff, 1024); } if (rNode.flags & Node::HasScale) { char buff[64]; dSprintf(buff, 63, ", %g", rNode.scaleFactor); - dStrcat(finalBuffer, buff); + dStrcat(finalBuffer, buff, 1024); } if (rNode.flags & Node::BindCmd) { if (rNode.makeConsoleCommand) { - dStrcat(finalBuffer, ", \""); - dStrcat(finalBuffer, rNode.makeConsoleCommand); - dStrcat(finalBuffer, "\""); + dStrcat(finalBuffer, ", \"", 1024); + dStrcat(finalBuffer, rNode.makeConsoleCommand, 1024); + dStrcat(finalBuffer, "\"", 1024); } else { - dStrcat(finalBuffer, ", \"\""); + dStrcat(finalBuffer, ", \"\"", 1024); } if (rNode.breakConsoleCommand) { - dStrcat(finalBuffer, ", \""); - dStrcat(finalBuffer, rNode.breakConsoleCommand); - dStrcat(finalBuffer, "\""); + dStrcat(finalBuffer, ", \"", 1024); + dStrcat(finalBuffer, rNode.breakConsoleCommand, 1024); + dStrcat(finalBuffer, "\"", 1024); } else - dStrcat(finalBuffer, ", \"\""); + dStrcat(finalBuffer, ", \"\"", 1024); } else if (rNode.flags & Node::Held) { - dStrcat(finalBuffer, ", "); - dStrcat(finalBuffer, rNode.consoleFunction); + dStrcat(finalBuffer, ", ", 1024); + dStrcat(finalBuffer, rNode.consoleFunction, 1024); - dStrcat(finalBuffer, ", "); - dStrcat(finalBuffer, rNode.contextEvent->mConsoleFunctionHeld); + dStrcat(finalBuffer, ", ", 1024); + dStrcat(finalBuffer, rNode.contextEvent->mConsoleFunctionHeld, 1024); } else { - dStrcat(finalBuffer, ", "); - dStrcat(finalBuffer, rNode.consoleFunction); + dStrcat(finalBuffer, ", ", 1024); + dStrcat(finalBuffer, rNode.consoleFunction, 1024); } - dStrcat(finalBuffer, ");"); + dStrcat(finalBuffer, ");", 1024); Con::printf(finalBuffer); } } @@ -786,8 +786,8 @@ const char* ActionMap::getBinding( const char* command ) { dSprintf( buffer, sizeof( buffer ), "%s\t%s%s", deviceBuffer, modifierString, keyBuffer ); if ( returnString[0] ) - dStrcat( returnString, "\t" ); - dStrcat( returnString, buffer ); + dStrcat( returnString, "\t", 1024 ); + dStrcat( returnString, buffer, 1024 ); } } diff --git a/Engine/source/sim/netStringTable.cpp b/Engine/source/sim/netStringTable.cpp index 117d0a020..d1a25e826 100644 --- a/Engine/source/sim/netStringTable.cpp +++ b/Engine/source/sim/netStringTable.cpp @@ -239,7 +239,7 @@ void NetStringTable::expandString(NetStringHandle &inString, char *buf, U32 bufS } buf[bufSize - 1] = 0; } else { - dStrcat(buf, ""); + dStrcat(buf, "", bufSize); } } diff --git a/Engine/source/terrain/terrData.cpp b/Engine/source/terrain/terrData.cpp index a97ec7e98..8665fa9f4 100644 --- a/Engine/source/terrain/terrData.cpp +++ b/Engine/source/terrain/terrData.cpp @@ -1306,7 +1306,7 @@ DefineEngineMethod( TerrainBlock, save, bool, ( const char* fileName),, dStrcpy(filename,fileName); char *ext = dStrrchr(filename, '.'); if (!ext || dStricmp(ext, ".ter") != 0) - dStrcat(filename, ".ter"); + dStrcat(filename, ".ter", 256); return static_cast(object)->save(filename); } @@ -1316,7 +1316,7 @@ DefineEngineMethod( TerrainBlock, save, bool, ( const char* fileName),, // dStrcpy(filename,argv[2]); // char *ext = dStrrchr(filename, '.'); // if (!ext || dStricmp(ext, ".ter") != 0) -// dStrcat(filename, ".ter"); +// dStrcat(filename, ".ter", 256); // return static_cast(object)->save(filename); //} From 79c34c68dbee952fa9cea2cd72ea8b8519608c04 Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Tue, 6 Mar 2018 01:59:05 -0500 Subject: [PATCH 14/26] Use strncpy instead of strcpy because again, buffer overflows --- Engine/source/T3D/components/component.cpp | 2 +- Engine/source/T3D/decal/decalManager.cpp | 2 +- Engine/source/T3D/fx/particle.cpp | 2 +- Engine/source/T3D/fx/particleEmitter.cpp | 2 +- Engine/source/T3D/item.cpp | 4 +- Engine/source/afx/afxMagicMissile.cpp | 2 +- Engine/source/afx/ce/afxParticleEmitter.cpp | 6 +-- Engine/source/afx/ea/afxEA_PhraseEffect.cpp | 6 +-- Engine/source/afx/rpg/afxRPGMagicSpell.cpp | 8 ++-- Engine/source/afx/ui/afxSpellButton.cpp | 16 ++++---- Engine/source/afx/xm/afxXM_PathConform.cpp | 2 +- Engine/source/app/badWordFilter.cpp | 6 +-- Engine/source/app/banList.cpp | 2 +- Engine/source/app/mainLoop.cpp | 2 +- Engine/source/app/net/net.cpp | 6 +-- Engine/source/app/net/netExamples.cpp | 4 +- Engine/source/app/net/serverQuery.cpp | 38 +++++++++---------- Engine/source/console/CMDscan.cpp | 2 +- Engine/source/console/SimXMLDocument.cpp | 4 +- Engine/source/console/astAlloc.cpp | 2 +- Engine/source/console/codeInterpreter.cpp | 26 ++++++------- Engine/source/console/compiler.cpp | 4 +- Engine/source/console/console.cpp | 30 +++++++-------- Engine/source/console/console.h | 2 +- Engine/source/console/consoleDoc.cpp | 4 +- Engine/source/console/consoleFunctions.cpp | 36 +++++++++--------- Engine/source/console/consoleInternal.cpp | 10 ++--- Engine/source/console/consoleObject.cpp | 2 +- Engine/source/console/fieldBrushObject.cpp | 4 +- Engine/source/console/fileSystemFunctions.cpp | 16 ++++---- Engine/source/console/persistenceManager.cpp | 2 +- Engine/source/console/scriptFilename.cpp | 8 ++-- Engine/source/console/sim.cpp | 4 +- Engine/source/console/simDatablock.cpp | 4 +- Engine/source/console/simObject.cpp | 16 ++++---- Engine/source/console/simObjectMemento.cpp | 2 +- Engine/source/console/stringStack.h | 2 +- Engine/source/core/stream/bitStream.cpp | 4 +- Engine/source/core/stringTable.cpp | 2 +- Engine/source/core/strings/findMatch.cpp | 6 +-- .../source/core/strings/stringFunctions.cpp | 2 +- Engine/source/core/strings/stringFunctions.h | 19 +++++++++- Engine/source/core/tokenizer.cpp | 6 +-- Engine/source/core/util/zip/centralDir.cpp | 2 +- Engine/source/gfx/Null/gfxNullDevice.cpp | 4 +- Engine/source/gfx/gfxStructs.cpp | 4 +- Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp | 4 +- .../source/gfx/gl/win32/gfxGLDevice.win.cpp | 4 +- Engine/source/gfx/screenshot.cpp | 2 +- Engine/source/gui/containers/guiFormCtrl.cpp | 2 +- .../source/gui/controls/guiAnimBitmapCtrl.cpp | 4 +- .../source/gui/controls/guiFileTreeCtrl.cpp | 2 +- Engine/source/gui/controls/guiPopUpCtrl.cpp | 9 +++-- Engine/source/gui/controls/guiPopUpCtrlEx.cpp | 9 +++-- Engine/source/gui/controls/guiTabPageCtrl.cpp | 2 +- .../source/gui/controls/guiTreeViewCtrl.cpp | 8 ++-- Engine/source/gui/core/guiControl.cpp | 2 +- Engine/source/gui/editor/guiDebugger.cpp | 6 +-- Engine/source/gui/editor/guiEditCtrl.cpp | 2 +- Engine/source/gui/editor/guiFilterCtrl.cpp | 2 +- Engine/source/gui/utility/messageVector.cpp | 2 +- Engine/source/i18n/lang.cpp | 18 ++++----- .../source/materials/materialDefinition.cpp | 10 ++--- Engine/source/module/moduleDefinition.h | 6 +-- Engine/source/module/moduleManager.cpp | 4 +- Engine/source/persistence/taml/taml.cpp | 4 +- Engine/source/persistence/taml/tamlCustom.cpp | 2 +- Engine/source/persistence/taml/tamlCustom.h | 4 +- .../source/persistence/taml/tamlWriteNode.h | 4 +- .../platform/nativeDialogs/fileDialog.cpp | 2 +- Engine/source/platform/platformFileIO.cpp | 2 +- Engine/source/platform/platformMemory.cpp | 2 +- Engine/source/platform/platformNet.cpp | 6 +-- Engine/source/platform/platformRedBook.cpp | 2 +- Engine/source/platform/profiler.cpp | 18 ++++----- Engine/source/platformMac/macFileIO.mm | 2 +- .../platformWin32/minidump/winMiniDump.cpp | 2 +- .../nativeDialogs/fileDialog.cpp | 10 ++--- .../source/platformWin32/winDInputDevice.cpp | 2 +- Engine/source/platformWin32/winFileio.cpp | 30 +++++++-------- Engine/source/platformWin32/winRedbook.cpp | 2 +- Engine/source/platformWin32/winWindow.cpp | 2 +- Engine/source/sfx/openal/sfxALProvider.cpp | 4 +- .../source/shaderGen/GLSL/shaderCompGLSL.cpp | 4 +- Engine/source/shaderGen/langElement.cpp | 4 +- Engine/source/shaderGen/shaderGen.cpp | 4 +- Engine/source/sim/actionMap.cpp | 12 +++--- Engine/source/sim/netDownload.cpp | 2 +- Engine/source/sim/netStringTable.cpp | 4 +- Engine/source/terrain/terrData.cpp | 4 +- Engine/source/util/messaging/eventManager.cpp | 2 +- Engine/source/util/undo.cpp | 4 +- 92 files changed, 298 insertions(+), 279 deletions(-) diff --git a/Engine/source/T3D/components/component.cpp b/Engine/source/T3D/components/component.cpp index 181c892e5..1ef7904e9 100644 --- a/Engine/source/T3D/components/component.cpp +++ b/Engine/source/T3D/components/component.cpp @@ -548,7 +548,7 @@ const char * Component::getDescriptionText(const char *desc) if (!Platform::isFile(desc)) { newDesc = new char[dStrlen(desc) + 1]; - dStrcpy(newDesc, desc); + dStrcpy(newDesc, desc, dStrlen(desc) + 1); return newDesc; } diff --git a/Engine/source/T3D/decal/decalManager.cpp b/Engine/source/T3D/decal/decalManager.cpp index ab53842e5..2a286ea37 100644 --- a/Engine/source/T3D/decal/decalManager.cpp +++ b/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'; diff --git a/Engine/source/T3D/fx/particle.cpp b/Engine/source/T3D/fx/particle.cpp index 823376fc7..a528af0d1 100644 --- a/Engine/source/T3D/fx/particle.cpp +++ b/Engine/source/T3D/fx/particle.cpp @@ -595,7 +595,7 @@ bool ParticleData::preload(bool server, String &errorStr) animTexFrames.clear(); char* tokCopy = new char[dStrlen(animTexFramesString) + 1]; - dStrcpy(tokCopy, animTexFramesString); + dStrcpy(tokCopy, animTexFramesString, dStrlen(animTexFramesString) + 1); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) diff --git a/Engine/source/T3D/fx/particleEmitter.cpp b/Engine/source/T3D/fx/particleEmitter.cpp index 4005607d7..00dbadb97 100644 --- a/Engine/source/T3D/fx/particleEmitter.cpp +++ b/Engine/source/T3D/fx/particleEmitter.cpp @@ -609,7 +609,7 @@ bool ParticleEmitterData::onAdd() // First we parse particleString into a list of particle name tokens Vector dataBlocks(__FILE__, __LINE__); char* tokCopy = new char[dStrlen(particleString) + 1]; - dStrcpy(tokCopy, particleString); + dStrcpy(tokCopy, particleString, dStrlen(particleString) + 1); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) diff --git a/Engine/source/T3D/item.cpp b/Engine/source/T3D/item.cpp index e6d21b93a..b710842d7 100644 --- a/Engine/source/T3D/item.cpp +++ b/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; } diff --git a/Engine/source/afx/afxMagicMissile.cpp b/Engine/source/afx/afxMagicMissile.cpp index 36ecd1777..690e3c74b 100644 --- a/Engine/source/afx/afxMagicMissile.cpp +++ b/Engine/source/afx/afxMagicMissile.cpp @@ -447,7 +447,7 @@ bool afxMagicMissileData::onAdd() // make a copy of points_string char* tokCopy = new char[dStrlen(wiggle_axis_string) + 1]; - dStrcpy(tokCopy, wiggle_axis_string); + dStrcpy(tokCopy, wiggle_axis_string, dStrlen(wiggle_axis_string) + 1); // extract tokens one by one, adding them to dataBlocks char* currTok = dStrtok(tokCopy, " \t"); diff --git a/Engine/source/afx/ce/afxParticleEmitter.cpp b/Engine/source/afx/ce/afxParticleEmitter.cpp index 3983b27ba..2f7643c8f 100644 --- a/Engine/source/afx/ce/afxParticleEmitter.cpp +++ b/Engine/source/afx/ce/afxParticleEmitter.cpp @@ -142,7 +142,7 @@ bool afxParticleEmitterData::onAdd() { Vector dataBlocks(__FILE__, __LINE__); char* tokCopy = new char[dStrlen(tpaths_string) + 1]; - dStrcpy(tokCopy, tpaths_string); + dStrcpy(tokCopy, tpaths_string, dStrlen(tpaths_string) + 1); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) @@ -468,7 +468,7 @@ bool afxParticleEmitterPathData::onAdd() { Vector dataBlocks(__FILE__, __LINE__); char* tokCopy = new char[dStrlen(epaths_string) + 1]; - dStrcpy(tokCopy, epaths_string); + dStrcpy(tokCopy, epaths_string, dStrlen(epaths_string) + 1); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) @@ -553,7 +553,7 @@ void afxParticleEmitterPathData::onPerformSubstitutions() { Vector dataBlocks(__FILE__, __LINE__); char* tokCopy = new char[dStrlen(epaths_string) + 1]; - dStrcpy(tokCopy, epaths_string); + dStrcpy(tokCopy, epaths_string, dStrlen(epaths_string) + 1); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) diff --git a/Engine/source/afx/ea/afxEA_PhraseEffect.cpp b/Engine/source/afx/ea/afxEA_PhraseEffect.cpp index 4448e1967..e253ab1ee 100644 --- a/Engine/source/afx/ea/afxEA_PhraseEffect.cpp +++ b/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); } -//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// \ No newline at end of file +//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// diff --git a/Engine/source/afx/rpg/afxRPGMagicSpell.cpp b/Engine/source/afx/rpg/afxRPGMagicSpell.cpp index 6490ad260..3e9362435 100644 --- a/Engine/source/afx/rpg/afxRPGMagicSpell.cpp +++ b/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,7 +225,7 @@ 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)", 32); } @@ -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); diff --git a/Engine/source/afx/ui/afxSpellButton.cpp b/Engine/source/afx/ui/afxSpellButton.cpp index 2ca1e4473..632d2e652 100644 --- a/Engine/source/afx/ui/afxSpellButton.cpp +++ b/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; diff --git a/Engine/source/afx/xm/afxXM_PathConform.cpp b/Engine/source/afx/xm/afxXM_PathConform.cpp index af9b7869f..3fde74699 100644 --- a/Engine/source/afx/xm/afxXM_PathConform.cpp +++ b/Engine/source/afx/xm/afxXM_PathConform.cpp @@ -195,7 +195,7 @@ bool afxXM_PathConformData::onAdd() { Vector dataBlocks(__FILE__, __LINE__); char* tokCopy = new char[dStrlen(paths_string) + 1]; - dStrcpy(tokCopy, paths_string); + dStrcpy(tokCopy, paths_string, dStrlen(paths_string) + 1); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) diff --git a/Engine/source/app/badWordFilter.cpp b/Engine/source/app/badWordFilter.cpp index d0547e5ee..d789bc1c4 100644 --- a/Engine/source/app/badWordFilter.cpp +++ b/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; } @@ -287,7 +287,7 @@ DefineEngineFunction(filterString, const char *, (const char* baseString, const replaceStr = gBadWordFilter->getDefaultReplaceStr(); char *ret = Con::getReturnBuffer(dStrlen(baseString) + 1); - dStrcpy(ret, baseString); + dStrcpy(ret, baseString, dStrlen(baseString)); gBadWordFilter->filterString(ret, replaceStr); return ret; } diff --git a/Engine/source/app/banList.cpp b/Engine/source/app/banList.cpp index 952b49a05..4e7de54a2 100644 --- a/Engine/source/app/banList.cpp +++ b/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; diff --git a/Engine/source/app/mainLoop.cpp b/Engine/source/app/mainLoop.cpp index 5fc4aa8c0..b08363f8a 100644 --- a/Engine/source/app/mainLoop.cpp +++ b/Engine/source/app/mainLoop.cpp @@ -495,7 +495,7 @@ bool StandardMainLoop::handleCommandLine( S32 argc, const char **argv ) S32 pathLen = dStrlen( fdd.mFile ); FrameTemp szPathCopy( pathLen + 1); - dStrcpy( szPathCopy, fdd.mFile ); + dStrcpy( szPathCopy, fdd.mFile, pathLen + 1 ); //forwardslash( szPathCopy ); const char *path = dStrrchr(szPathCopy, '/'); diff --git a/Engine/source/app/net/net.cpp b/Engine/source/app/net/net.cpp index f668d2651..c5f1be189 100644 --- a/Engine/source/app/net/net.cpp +++ b/Engine/source/app/net/net.cpp @@ -128,7 +128,7 @@ const char *rmtCommandName = dStrchr(mArgv[1], ' ') + 1; if(conn->isConnectionToServer()) { - dStrcpy(mBuf, "clientCmd"); + dStrcpy(mBuf, "clientCmd", 1024); dStrcat(mBuf, rmtCommandName, 1024); char *temp = mArgv[1]; @@ -139,7 +139,7 @@ } else { - dStrcpy(mBuf, "serverCmd"); + dStrcpy(mBuf, "serverCmd", 1024); dStrcat(mBuf, rmtCommandName, 1024); char *temp = mArgv[1]; @@ -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; diff --git a/Engine/source/app/net/netExamples.cpp b/Engine/source/app/net/netExamples.cpp index 81065ce6a..1f53c6d21 100644 --- a/Engine/source/app/net/netExamples.cpp +++ b/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); diff --git a/Engine/source/app/net/serverQuery.cpp b/Engine/source/app/net/serverQuery.cpp index 4c91caf70..12a83c454 100644 --- a/Engine/source/app/net/serverQuery.cpp +++ b/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; @@ -511,13 +511,13 @@ void queryMasterServer(U8 flags, const char* gameType, const char* missionType, if ( !sActiveFilter.gameType || dStrcmp( sActiveFilter.gameType, gameType ) != 0 ) { sActiveFilter.gameType = (char*) dRealloc( sActiveFilter.gameType, dStrlen( gameType ) + 1 ); - dStrcpy( sActiveFilter.gameType, gameType ); + dStrcpy( sActiveFilter.gameType, gameType, dStrlen(gameType) + 1 ); } if ( !sActiveFilter.missionType || dStrcmp( sActiveFilter.missionType, missionType ) != 0 ) { sActiveFilter.missionType = (char*) dRealloc( sActiveFilter.missionType, dStrlen( missionType ) + 1 ); - dStrcpy( sActiveFilter.missionType, missionType ); + dStrcpy( sActiveFilter.missionType, missionType, dStrlen(missionType) + 1 ); } sActiveFilter.queryFlags = flags | ServerFilter::NewStyleResponse; @@ -970,7 +970,7 @@ static void pushServerFavorites() 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 ); + dStrcpy( si->name, serverName, dStrlen(serverName) + 1 ); si->isFavorite = true; pushPingRequest( &addr ); } @@ -1054,13 +1054,13 @@ void addFakeServers( S32 howMany ) char buf[256]; dSprintf( buf, 255, "Fake server #%d", sNumFakeServers ); newServer.name = (char*) dMalloc( dStrlen( buf ) + 1 ); - dStrcpy( newServer.name, buf ); + dStrcpy( newServer.name, buf, strlen(buf) + 1 ); 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 +1353,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 ); @@ -1754,7 +1754,7 @@ static void handleGameMasterInfoRequest( const NetAddress* address, U32 key, U8 const char* guidList = Con::getVariable( "Server::GuidList" ); char* buf = new char[dStrlen( guidList ) + 1]; - dStrcpy( buf, guidList ); + dStrcpy( buf, guidList, dStrlen(guidList) + 1 ); char* temp = dStrtok( buf, "\t" ); temp8 = 0; for ( ; temp && temp8 < playerCount; temp8++ ) @@ -1949,7 +1949,7 @@ static void handleGamePingResponse( const NetAddress* address, BitStream* stream if ( !si->name ) { si->name = (char*) dMalloc( dStrlen( buf ) + 1 ); - dStrcpy( si->name, buf ); + dStrcpy( si->name, buf, dStrlen(buf) + 1 ); } // Set the server up to be queried: @@ -2051,7 +2051,7 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream if ( !si->gameType || dStricmp( si->gameType, stringBuf ) != 0 ) { si->gameType = (char*) dRealloc( (void*) si->gameType, dStrlen( stringBuf ) + 1 ); - dStrcpy( si->gameType, stringBuf ); + dStrcpy( si->gameType, stringBuf, dStrlen(stringBuf) + 1 ); // Test against the active filter: if ( applyFilter && dStricmp( sActiveFilter.gameType, "any" ) != 0 @@ -2068,7 +2068,7 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream if ( !si->missionType || dStrcmp( si->missionType, stringBuf ) != 0 ) { si->missionType = (char*) dRealloc( (void*) si->missionType, dStrlen( stringBuf ) + 1 ); - dStrcpy( si->missionType, stringBuf ); + dStrcpy( si->missionType, stringBuf, dStrlen(stringBuf) + 1 ); // Test against the active filter: if ( applyFilter && dStricmp( sActiveFilter.missionType, "any" ) != 0 @@ -2089,7 +2089,7 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream if ( !si->missionName || dStrcmp( si->missionName, stringBuf ) != 0 ) { si->missionName = (char*) dRealloc( (void*) si->missionName, dStrlen( stringBuf ) + 1 ); - dStrcpy( si->missionName, stringBuf ); + dStrcpy( si->missionName, stringBuf, dStrlen(stringBuf) + 1 ); } // Get the server status: @@ -2158,7 +2158,7 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream if ( !si->statusString || ( isUpdate && dStrcmp( si->statusString, stringBuf ) != 0 ) ) { si->infoString = (char*) dRealloc( (void*) si->infoString, dStrlen( stringBuf ) + 1 ); - dStrcpy( si->infoString, stringBuf ); + dStrcpy( si->infoString, stringBuf, dStrlen(stringBuf) + 1 ); } // Get the content string: @@ -2166,7 +2166,7 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream if ( !si->statusString || ( isUpdate && dStrcmp( si->statusString, stringBuf ) != 0 ) ) { si->statusString = (char*) dRealloc( (void*) si->statusString, dStrlen( stringBuf ) + 1 ); - dStrcpy( si->statusString, stringBuf ); + dStrcpy( si->statusString, stringBuf, dStrlen(stringBuf) + 1 ); } // Update the server browser gui! diff --git a/Engine/source/console/CMDscan.cpp b/Engine/source/console/CMDscan.cpp index 733460b09..c780fd2a6 100644 --- a/Engine/source/console/CMDscan.cpp +++ b/Engine/source/console/CMDscan.cpp @@ -2341,7 +2341,7 @@ static int Sc_ScanString(int ret) return -1; char* buffer = (char*)consoleAlloc(dStrlen(CMDtext)); - dStrcpy(buffer, CMDtext + 1); + dStrcpy(buffer, CMDtext + 1, dStrlen(CMDtext)); CMDlval.str = MakeToken< char* >(buffer, lineIndex); return ret; diff --git a/Engine/source/console/SimXMLDocument.cpp b/Engine/source/console/SimXMLDocument.cpp index b2960105b..4071ae138 100644 --- a/Engine/source/console/SimXMLDocument.cpp +++ b/Engine/source/console/SimXMLDocument.cpp @@ -833,7 +833,7 @@ void SimXMLDocument::setObjectAttributes(const char* objectID) continue; FrameTemp valCopy( dStrlen( val ) + 1 ); - dStrcpy( (char *)valCopy, val ); + dStrcpy( (char *)valCopy, val, dStrlen(val) + 1 ); if (!pObject->writeField(itr->pFieldname, valCopy)) continue; @@ -873,7 +873,7 @@ void SimXMLDocument::setObjectAttributes(const char* objectID) // continue; // FrameTemp valCopy( dStrlen( val ) + 1 ); - // dStrcpy( (char *)valCopy, val ); + // dStrcpy( (char *)valCopy, val, dStrlen(val) + 1 ); // if (!pObject->writeField(itr->pFieldname, valCopy)) // continue; diff --git a/Engine/source/console/astAlloc.cpp b/Engine/source/console/astAlloc.cpp index 75fbe151c..e897af247 100644 --- a/Engine/source/console/astAlloc.cpp +++ b/Engine/source/console/astAlloc.cpp @@ -241,7 +241,7 @@ StrConstNode *StrConstNode::alloc(S32 lineNumber, char *str, bool tag, bool doc) ret->str = (char *)consoleAlloc(dStrlen(str) + 1); ret->tag = tag; ret->doc = doc; - dStrcpy(ret->str, str); + dStrcpy(ret->str, str, dStrlen(str) + 1); return ret; } diff --git a/Engine/source/console/codeInterpreter.cpp b/Engine/source/console/codeInterpreter.cpp index 0b5986fda..46d58476e 100644 --- a/Engine/source/console/codeInterpreter.cpp +++ b/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) { @@ -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; diff --git a/Engine/source/console/compiler.cpp b/Engine/source/console/compiler.cpp index 0330f4d59..716b9e377 100644 --- a/Engine/source/console/compiler.cpp +++ b/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; } diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index ff204a448..fd5d343d2 100644 --- a/Engine/source/console/console.cpp +++ b/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; @@ -647,7 +647,7 @@ static void _printf(ConsoleLogEntry::Level level, ConsoleLogEntry::Type type, co 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(entry.mString), pos); + dStrcpy(const_cast(entry.mString), pos, dStrlen(pos) + 1); // This prevents infinite recursion if the console itself needs to // re-allocate memory to accommodate the new console log entry, and @@ -1271,7 +1271,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 +2097,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 +2118,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 +2143,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 +2183,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 +2208,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 +2300,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 +2353,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 +2616,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; diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index 4009a5393..a734cefbf 100644 --- a/Engine/source/console/console.h +++ b/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); diff --git a/Engine/source/console/consoleDoc.cpp b/Engine/source/console/consoleDoc.cpp index 4fb6921dd..f4b74402b 100644 --- a/Engine/source/console/consoleDoc.cpp +++ b/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 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 ); diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index 16c20c3c3..3ffe200ce 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/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 ); @@ -585,7 +586,7 @@ DefineConsoleFunction( strlwr, const char*, ( const char* str ),, "@ingroup Strings" ) { char *ret = Con::getReturnBuffer(dStrlen(str) + 1); - dStrcpy(ret, str); + dStrcpy(ret, str, dStrlen(str) + 1); return dStrlwr(ret); } @@ -602,7 +603,7 @@ DefineConsoleFunction( strupr, const char*, ( const char* str ),, "@ingroup Strings" ) { char *ret = Con::getReturnBuffer(dStrlen(str) + 1); - dStrcpy(ret, str); + dStrcpy(ret, str, dStrlen(str) + 1); return dStrupr(ret); } @@ -663,7 +664,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 +673,13 @@ DefineConsoleFunction( strreplace, const char*, ( const char* source, const char const char *scan = dStrstr(source + scanp, from); if(!scan) { - dStrcpy(ret + dstp, source + scanp); + dStrcpy(ret + dstp, source + scanp, retLen - dstp); return ret; } U32 len = scan - (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 +903,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 +954,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 ); @@ -1825,7 +1827,7 @@ DefineEngineFunction( detag, const char*, ( const char* str ),, return ""; char* ret = Con::getReturnBuffer( dStrlen( word + 1 ) + 1 ); - dStrcpy( ret, word + 1 ); + dStrcpy( ret, word + 1, dStrlen(word + 1) + 1 ); return ret; } else @@ -1889,7 +1891,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], len); + dStrcat(ret, argv[i], len + 1); Con::printf("%s", ret); ret[0] = 0; @@ -1913,7 +1915,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], len); + dStrcat(ret, argv[i], len + 1); Con::warnf(ConsoleLogEntry::General, "%s", ret); ret[0] = 0; @@ -1937,7 +1939,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], len); + dStrcat(ret, argv[i], len + 1); Con::errorf(ConsoleLogEntry::General, "%s", ret); ret[0] = 0; diff --git a/Engine/source/console/consoleInternal.cpp b/Engine/source/console/consoleInternal.cpp index 3f5c78f67..61a63ae1e 100644 --- a/Engine/source/console/consoleInternal.cpp +++ b/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; } @@ -1360,7 +1360,7 @@ 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, 1024); @@ -1381,7 +1381,7 @@ 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, 1024); diff --git a/Engine/source/console/consoleObject.cpp b/Engine/source/console/consoleObject.cpp index 32c84f20b..4064d47da 100644 --- a/Engine/source/console/consoleObject.cpp +++ b/Engine/source/console/consoleObject.cpp @@ -773,7 +773,7 @@ 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", bufSize ); diff --git a/Engine/source/console/fieldBrushObject.cpp b/Engine/source/console/fieldBrushObject.cpp index e96387cae..0caf00e48 100644 --- a/Engine/source/console/fieldBrushObject.cpp +++ b/Engine/source/console/fieldBrushObject.cpp @@ -273,7 +273,7 @@ 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", 256 ); // Store Group. @@ -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 ) ); diff --git a/Engine/source/console/fileSystemFunctions.cpp b/Engine/source/console/fileSystemFunctions.cpp index d8531ff7c..ec2d9c17d 100644 --- a/Engine/source/console/fileSystemFunctions.cpp +++ b/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 szPathCopy( pathLen + 1); - dStrcpy( szPathCopy, fileName ); + dStrcpy( szPathCopy, fileName, pathLen + 1 ); forwardslash( szPathCopy ); const char *path = dStrrchr(szPathCopy, '/'); @@ -618,7 +618,7 @@ DefineEngineFunction(fileBase, String, ( const char* fileName ),, else path++; char *ret = Con::getReturnBuffer(dStrlen(path) + 1); - dStrcpy(ret, path); + dStrcpy(ret, path, dStrlen(path) + 1); char *ext = dStrrchr(ret, '.'); if(ext) *ext = 0; @@ -635,7 +635,7 @@ DefineEngineFunction(fileName, String, ( const char* fileName ),, S32 pathLen = dStrlen( fileName ); FrameTemp szPathCopy( pathLen + 1); - dStrcpy( szPathCopy, fileName ); + dStrcpy( szPathCopy, fileName, pathLen + 1 ); forwardslash( szPathCopy ); const char *name = dStrrchr(szPathCopy, '/'); @@ -644,7 +644,7 @@ DefineEngineFunction(fileName, String, ( const char* fileName ),, else name++; char *ret = Con::getReturnBuffer(dStrlen(name)); - dStrcpy(ret, name); + dStrcpy(ret, name, dStrlen(name)); return ret; } @@ -658,7 +658,7 @@ DefineEngineFunction(filePath, String, ( const char* fileName ),, S32 pathLen = dStrlen( fileName ); FrameTemp szPathCopy( pathLen + 1); - dStrcpy( szPathCopy, fileName ); + dStrcpy( szPathCopy, fileName, pathLen + 1 ); forwardslash( szPathCopy ); const char *path = dStrrchr(szPathCopy, '/'); diff --git a/Engine/source/console/persistenceManager.cpp b/Engine/source/console/persistenceManager.cpp index db7b7254e..df2dd8b01 100644 --- a/Engine/source/console/persistenceManager.cpp +++ b/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 diff --git a/Engine/source/console/scriptFilename.cpp b/Engine/source/console/scriptFilename.cpp index 9455826f7..332f01d26 100644 --- a/Engine/source/console/scriptFilename.cpp +++ b/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; } diff --git a/Engine/source/console/sim.cpp b/Engine/source/console/sim.cpp index 0ea902b5c..cb01e8019 100644 --- a/Engine/source/console/sim.cpp +++ b/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; } diff --git a/Engine/source/console/simDatablock.cpp b/Engine/source/console/simDatablock.cpp index ce689c054..e2984c16a 100644 --- a/Engine/source/console/simDatablock.cpp +++ b/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++) { diff --git a/Engine/source/console/simObject.cpp b/Engine/source/console/simObject.cpp index 0d2e5eb32..b47448414 100644 --- a/Engine/source/console/simObject.cpp +++ b/Engine/source/console/simObject.cpp @@ -320,7 +320,7 @@ void SimObject::writeFields(Stream &stream, U32 tabStop) U32 nBufferSize = dStrlen( val ) + 1; FrameTemp valCopy( nBufferSize ); - dStrcpy( (char *)valCopy, val ); + dStrcpy( (char *)valCopy, val, nBufferSize ); if (!writeField(f->pFieldname, valCopy)) continue; @@ -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,7 +1028,7 @@ void SimObject::setDataField(StringTableEntry slotName, const char *array, const else { char buf[256]; - dStrcpy(buf, slotName); + dStrcpy(buf, slotName, 256); dStrcat(buf, array, 256); StringTableEntry permanentSlotName = StringTable->insert(buf); mFieldDictionary->setFieldValue(permanentSlotName, value); @@ -1069,7 +1069,7 @@ const char *SimObject::getDataField(StringTableEntry slotName, const char *array else { static char buf[256]; - dStrcpy(buf, slotName); + dStrcpy(buf, slotName, 256); dStrcat(buf, array, 256); if (const char* val = mFieldDictionary->getFieldValue(StringTable->insert(buf))) return val; @@ -1310,7 +1310,7 @@ U32 SimObject::getDataFieldType( StringTableEntry slotName, const char* array ) else { static char buf[256]; - dStrcpy( buf, slotName ); + dStrcpy( buf, slotName, 256 ); dStrcat( buf, array, 256 ); return mFieldDictionary->getFieldType( StringTable->insert( buf ) ); @@ -1333,7 +1333,7 @@ void SimObject::setDataFieldType(const U32 fieldTypeId, StringTableEntry slotNam else { static char buf[256]; - dStrcpy( buf, slotName ); + dStrcpy( buf, slotName, 256 ); dStrcat( buf, array, 256 ); mFieldDictionary->setFieldType( StringTable->insert( buf ), fieldTypeId ); @@ -1354,7 +1354,7 @@ void SimObject::setDataFieldType(const char *typeName, StringTableEntry slotName else { static char buf[256]; - dStrcpy( buf, slotName ); + dStrcpy( buf, slotName, 256 ); dStrcat( buf, array, 256 ); StringTableEntry permanentSlotName = StringTable->insert(buf); diff --git a/Engine/source/console/simObjectMemento.cpp b/Engine/source/console/simObjectMemento.cpp index ef2e8f732..93a9db118 100644 --- a/Engine/source/console/simObjectMemento.cpp +++ b/Engine/source/console/simObjectMemento.cpp @@ -137,7 +137,7 @@ SimObject *SimObjectMemento::restore() const tempBuffer = ( char* ) dMalloc( dStrlen( mState ) + uniqueNameLen + 1 ); dMemcpy( tempBuffer, mState, numCharsToLeftParen ); dMemcpy( &tempBuffer[ numCharsToLeftParen ], uniqueName, uniqueNameLen ); - dStrcpy( &tempBuffer[ numCharsToLeftParen + uniqueNameLen ], &mState[ numCharsToLeftParen ] ); + dStrcpy( &tempBuffer[ numCharsToLeftParen + uniqueNameLen ], &mState[ numCharsToLeftParen ], dStrlen(mState) - numCharsToLeftParen + 1 ); } Con::evaluate( tempBuffer ); diff --git a/Engine/source/console/stringStack.h b/Engine/source/console/stringStack.h index d76ad71ec..0550bb61e 100644 --- a/Engine/source/console/stringStack.h +++ b/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. diff --git a/Engine/source/core/stream/bitStream.cpp b/Engine/source/core/stream/bitStream.cpp index f80389640..3ee527a04 100644 --- a/Engine/source/core/stream/bitStream.cpp +++ b/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) diff --git a/Engine/source/core/stringTable.cpp b/Engine/source/core/stringTable.cpp index 9a71603ae..17f2ca235 100644 --- a/Engine/source/core/stringTable.cpp +++ b/Engine/source/core/stringTable.cpp @@ -145,7 +145,7 @@ StringTableEntry _StringTable::insert(const char* _val, const bool caseSens) *walk = (Node *) mempool.alloc(sizeof(Node)); (*walk)->next = 0; (*walk)->val = (char *) mempool.alloc(dStrlen(val) + 1); - dStrcpy((*walk)->val, val); + dStrcpy((*walk)->val, val, dStrlen(val) + 1); ret = (*walk)->val; itemCount ++; } diff --git a/Engine/source/core/strings/findMatch.cpp b/Engine/source/core/strings/findMatch.cpp index 1bb35128e..bfa7d5a3b 100644 --- a/Engine/source/core/strings/findMatch.cpp +++ b/Engine/source/core/strings/findMatch.cpp @@ -72,7 +72,7 @@ void FindMatch::setExpression( const char *_expression ) delete [] expression; expression = new char[dStrlen(_expression) + 1]; - dStrcpy(expression, _expression); + dStrcpy(expression, _expression, dStrlen(_expression) + 1); dStrupr(expression); } @@ -82,7 +82,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 +143,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. diff --git a/Engine/source/core/strings/stringFunctions.cpp b/Engine/source/core/strings/stringFunctions.cpp index 3fe24c7f1..93db4fd47 100644 --- a/Engine/source/core/strings/stringFunctions.cpp +++ b/Engine/source/core/strings/stringFunctions.cpp @@ -216,7 +216,7 @@ 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); + dStrcpy(buffer, src, dStrlen(src) + 1); return buffer; } diff --git a/Engine/source/core/strings/stringFunctions.h b/Engine/source/core/strings/stringFunctions.h index 4c79bf32d..e4307a092 100644 --- a/Engine/source/core/strings/stringFunctions.h +++ b/Engine/source/core/strings/stringFunctions.h @@ -47,6 +47,7 @@ #endif // defined(TORQUE_OS_WIN) +#define DEBUG_CHECK_OVERFLOW 1 //------------------------------------------------------------------------------ // standard string functions [defined in platformString.cpp] @@ -60,12 +61,16 @@ inline char *dStrcat(char *dst, const char *src) inline char *dStrcat(char *dst, const char *src, dsize_t len) { +#ifdef DEBUG_CHECK_OVERFLOW + if (strlen(src) >= len) { + AssertWarn(false, "dStrcat out of range"); + } +#endif return strncat(dst,src,len - 1); //Safety because strncat copies at most len+1 characters } inline char *dStrncat(char *dst, const char *src, dsize_t len) { - AssertFatal(false, "Use dStrcat with length"); return dStrcat(dst, src, len); } @@ -94,9 +99,21 @@ inline S32 dStrnicmp(const char *str1, const char *str2, dsize_t len) return strncasecmp( str1, str2, len ); } +/// @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); +} + +inline char *dStrcpy(char *dst, const char *src, dsize_t len) +{ +#ifdef DEBUG_CHECK_OVERFLOW + if (strlen(src) >= len) { + AssertWarn(false, "dStrcpy out of range"); + } +#endif + return strncpy(dst,src,len); } inline char *dStrncpy(char *dst, const char *src, dsize_t len) diff --git a/Engine/source/core/tokenizer.cpp b/Engine/source/core/tokenizer.cpp index a51d3d5ad..6d155d18a 100644 --- a/Engine/source/core/tokenizer.cpp +++ b/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; -} \ No newline at end of file +} diff --git a/Engine/source/core/util/zip/centralDir.cpp b/Engine/source/core/util/zip/centralDir.cpp index e107df2e8..bf5bef92e 100644 --- a/Engine/source/core/util/zip/centralDir.cpp +++ b/Engine/source/core/util/zip/centralDir.cpp @@ -178,7 +178,7 @@ void CentralDir::setFileComment(const char *comment) { SAFE_DELETE_ARRAY(mFileComment); mFileComment = new char [dStrlen(comment)+1]; - dStrcpy(mFileComment, comment); + dStrcpy(mFileComment, comment, dStrlen(comment)+1); } //----------------------------------------------------------------------------- diff --git a/Engine/source/gfx/Null/gfxNullDevice.cpp b/Engine/source/gfx/Null/gfxNullDevice.cpp index f22e3bc7a..6b2b0b659 100644 --- a/Engine/source/gfx/Null/gfxNullDevice.cpp +++ b/Engine/source/gfx/Null/gfxNullDevice.cpp @@ -309,7 +309,7 @@ void GFXNullDevice::enumerateAdapters( Vector &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; \ No newline at end of file +static GFXNullRegisterDevice pNullRegisterDevice; diff --git a/Engine/source/gfx/gfxStructs.cpp b/Engine/source/gfx/gfxStructs.cpp index dca361af1..ff8726b8b 100644 --- a/Engine/source/gfx/gfxStructs.cpp +++ b/Engine/source/gfx/gfxStructs.cpp @@ -40,7 +40,7 @@ void GFXVideoMode::parseFromString( const char *str ) // Copy the string, as dStrtok is destructive char *tempBuf = new char[dStrlen( str ) + 1]; - dStrcpy( tempBuf, str ); + dStrcpy( tempBuf, str, dStrlen(str) + 1 ); #define PARSE_ELEM(type, var, func, tokParam, sep) \ if(const char *ptr = dStrtok( tokParam, sep)) \ @@ -76,4 +76,4 @@ void GFXShaderMacro::stringize( const Vector ¯os, String *ou } (*outString) += ";"; } -} \ No newline at end of file +} diff --git a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp index d909750b9..79308ce1c 100644 --- a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp +++ b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp @@ -128,11 +128,11 @@ void GFXGLDevice::enumerateAdapters( Vector &adapterList ) if (renderer) { - dStrcpy(toAdd->mName, renderer); + 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; diff --git a/Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp b/Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp index eaf7d1449..cb71ca48c 100644 --- a/Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp +++ b/Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp @@ -129,11 +129,11 @@ void GFXGLDevice::enumerateAdapters( Vector &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; diff --git a/Engine/source/gfx/screenshot.cpp b/Engine/source/gfx/screenshot.cpp index f10802bf3..1ba48d75d 100644 --- a/Engine/source/gfx/screenshot.cpp +++ b/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)); diff --git a/Engine/source/gui/containers/guiFormCtrl.cpp b/Engine/source/gui/containers/guiFormCtrl.cpp index a185af1e2..0c562d49d 100644 --- a/Engine/source/gui/containers/guiFormCtrl.cpp +++ b/Engine/source/gui/containers/guiFormCtrl.cpp @@ -218,7 +218,7 @@ bool GuiFormCtrl::resize(const Point2I &newPosition, const Point2I &newExtent) S32 strlen = dStrlen((const char*)mCaption); for(S32 i=strlen; i>=0; --i) { - dStrcpy(buf, ""); + dStrcpy(buf, "", i); dStrcat(buf, (const char*)mCaption, i); dStrcat(buf, "...", i); diff --git a/Engine/source/gui/controls/guiAnimBitmapCtrl.cpp b/Engine/source/gui/controls/guiAnimBitmapCtrl.cpp index eff5f1410..1f29caddc 100644 --- a/Engine/source/gui/controls/guiAnimBitmapCtrl.cpp +++ b/Engine/source/gui/controls/guiAnimBitmapCtrl.cpp @@ -168,7 +168,7 @@ bool guiAnimBitmapCtrl::ptSetFrameRanges(void *object, const char *index, const return true; } char* tokCopy = new char[dStrlen(data) + 1]; - dStrcpy(tokCopy, data); + dStrcpy(tokCopy, data, dStrlen(data) + 1); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) @@ -291,4 +291,4 @@ void guiAnimBitmapCtrl::onRender(Point2I offset, const RectI &updateRect) } renderChildControls(offset, updateRect); -} \ No newline at end of file +} diff --git a/Engine/source/gui/controls/guiFileTreeCtrl.cpp b/Engine/source/gui/controls/guiFileTreeCtrl.cpp index db38fbe58..b6531fbaa 100644 --- a/Engine/source/gui/controls/guiFileTreeCtrl.cpp +++ b/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; diff --git a/Engine/source/gui/controls/guiPopUpCtrl.cpp b/Engine/source/gui/controls/guiPopUpCtrl.cpp index af172221a..0697c6a36 100644 --- a/Engine/source/gui/controls/guiPopUpCtrl.cpp +++ b/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; diff --git a/Engine/source/gui/controls/guiPopUpCtrlEx.cpp b/Engine/source/gui/controls/guiPopUpCtrlEx.cpp index 3c6415117..fc7811e69 100644 --- a/Engine/source/gui/controls/guiPopUpCtrlEx.cpp +++ b/Engine/source/gui/controls/guiPopUpCtrlEx.cpp @@ -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; diff --git a/Engine/source/gui/controls/guiTabPageCtrl.cpp b/Engine/source/gui/controls/guiTabPageCtrl.cpp index ada0a2712..c87363cde 100644 --- a/Engine/source/gui/controls/guiTabPageCtrl.cpp +++ b/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; } diff --git a/Engine/source/gui/controls/guiTreeViewCtrl.cpp b/Engine/source/gui/controls/guiTreeViewCtrl.cpp index 9d45147e1..a4c5aff70 100644 --- a/Engine/source/gui/controls/guiTreeViewCtrl.cpp +++ b/Engine/source/gui/controls/guiTreeViewCtrl.cpp @@ -4754,15 +4754,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; } @@ -5570,4 +5570,4 @@ DefineEngineMethod(GuiTreeViewCtrl, getItemAtPosition, S32, (Point2I position), "@return The id of the item under the position.") { return object->getItemAtPosition(position); -} \ No newline at end of file +} diff --git a/Engine/source/gui/core/guiControl.cpp b/Engine/source/gui/core/guiControl.cpp index 968fc9a16..6fded2e92 100644 --- a/Engine/source/gui/core/guiControl.cpp +++ b/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; } diff --git a/Engine/source/gui/editor/guiDebugger.cpp b/Engine/source/gui/editor/guiDebugger.cpp index b77a909e4..fb888538a 100644 --- a/Engine/source/gui/editor/guiDebugger.cpp +++ b/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'; diff --git a/Engine/source/gui/editor/guiEditCtrl.cpp b/Engine/source/gui/editor/guiEditCtrl.cpp index 09644d990..571d1df84 100644 --- a/Engine/source/gui/editor/guiEditCtrl.cpp +++ b/Engine/source/gui/editor/guiEditCtrl.cpp @@ -2626,7 +2626,7 @@ DefineConsoleMethod( GuiEditCtrl, getSelectionGlobalBounds, const char*, (), , " 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() ); + dStrcpy( buffer, str.c_str(), str.length() ); return buffer; } diff --git a/Engine/source/gui/editor/guiFilterCtrl.cpp b/Engine/source/gui/editor/guiFilterCtrl.cpp index 6b7662bd5..67a0232ae 100644 --- a/Engine/source/gui/editor/guiFilterCtrl.cpp +++ b/Engine/source/gui/editor/guiFilterCtrl.cpp @@ -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) { diff --git a/Engine/source/gui/utility/messageVector.cpp b/Engine/source/gui/utility/messageVector.cpp index 2ee18387f..19255e38b 100644 --- a/Engine/source/gui/utility/messageVector.cpp +++ b/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; diff --git a/Engine/source/i18n/lang.cpp b/Engine/source/i18n/lang.cpp index 24f2e2d59..3ed0d344c 100644 --- a/Engine/source/i18n/lang.cpp +++ b/Engine/source/i18n/lang.cpp @@ -43,7 +43,7 @@ LangFile::LangFile(const UTF8 *langName /* = NULL */) if(langName) { mLangName = new UTF8 [dStrlen(langName) + 1]; - dStrcpy(mLangName, langName); + dStrcpy(mLangName, langName, dStrlen(langName) + 1); } else mLangName = NULL; @@ -137,7 +137,7 @@ const UTF8 * LangFile::getString(U32 id) U32 LangFile::addString(const UTF8 *str) { UTF8 *newstr = new UTF8 [dStrlen(str) + 1]; - dStrcpy(newstr, str); + dStrcpy(newstr, str, dStrlen(str) + 1); mStringTable.push_back(newstr); return mStringTable.size() - 1; } @@ -157,7 +157,7 @@ void LangFile::setString(U32 id, const UTF8 *str) SAFE_DELETE_ARRAY(mStringTable[id]); UTF8 *newstr = new UTF8 [dStrlen(str) + 1]; - dStrcpy(newstr, str); + dStrcpy(newstr, str, dStrlen(str) + 1); mStringTable[id] = newstr; } @@ -167,7 +167,7 @@ void LangFile::setLangName(const UTF8 *newName) delete [] mLangName; mLangName = new UTF8 [dStrlen(newName) + 1]; - dStrcpy(mLangName, newName); + dStrcpy(mLangName, newName, dStrlen(newName) + 1); } void LangFile::setLangFile(const UTF8 *langFile) @@ -176,7 +176,7 @@ void LangFile::setLangFile(const UTF8 *langFile) delete [] mLangFile; mLangFile = new UTF8 [dStrlen(langFile) + 1]; - dStrcpy(mLangFile, langFile); + dStrcpy(mLangFile, langFile, dStrlen(langFile) + 1); } bool LangFile::activateLanguage() @@ -350,7 +350,7 @@ DefineConsoleMethod(LangTable, getString, const char *, (U32 id), , if(str != NULL) { char * ret = Con::getReturnBuffer(dStrlen(str) + 1); - dStrcpy(ret, str); + dStrcpy(ret, str, dStrlen(str) + 1); return ret; } @@ -388,7 +388,7 @@ DefineConsoleMethod(LangTable, getLangName, const char *, (S32 langId), , "(int if(str != NULL) { char * ret = Con::getReturnBuffer(dStrlen(str) + 1); - dStrcpy(ret, str); + dStrcpy(ret, str, dStrlen(str) + 1); return ret; } @@ -414,7 +414,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 +575,4 @@ ConsoleFunction(CompileLanguage, void, 2, 3, "(string inputFile, [bool createMap delete mapStream; } } -//end lang_ localization \ No newline at end of file +//end lang_ localization diff --git a/Engine/source/materials/materialDefinition.cpp b/Engine/source/materials/materialDefinition.cpp index d116fe0f3..3ef1b1d01 100644 --- a/Engine/source/materials/materialDefinition.cpp +++ b/Engine/source/materials/materialDefinition.cpp @@ -654,33 +654,33 @@ 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", 512); } if(object->mAnimFlags[ id ] & Material::Wave) { if(dStrcmp( animFlags, "" ) == 0) - dStrcpy( animFlags, "$Wave" ); + dStrcpy( animFlags, "$Wave", 512 ); else 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", 512); } if(object->mAnimFlags[ id ] & Material::Sequence) { if(dStrcmp( animFlags, "" ) == 0) - dStrcpy( animFlags, "$Sequence" ); + dStrcpy( animFlags, "$Sequence", 512 ); else dStrcat( animFlags, " | $Sequence", 512); } diff --git a/Engine/source/module/moduleDefinition.h b/Engine/source/module/moduleDefinition.h index 42deff44d..8652876cf 100644 --- a/Engine/source/module/moduleDefinition.h +++ b/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 ); diff --git a/Engine/source/module/moduleManager.cpp b/Engine/source/module/moduleManager.cpp index fa53728b7..ec45ad918 100644 --- a/Engine/source/module/moduleManager.cpp +++ b/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; } diff --git a/Engine/source/persistence/taml/taml.cpp b/Engine/source/persistence/taml/taml.cpp index f364ed0ce..9b9c3bfa7 100644 --- a/Engine/source/persistence/taml/taml.cpp +++ b/Engine/source/persistence/taml/taml.cpp @@ -708,7 +708,7 @@ ImplementEnumType(_TamlFormatMode, U32 nBufferSize = dStrlen(pFieldValue) + 1; FrameTemp 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); - } \ No newline at end of file + } diff --git a/Engine/source/persistence/taml/tamlCustom.cpp b/Engine/source/persistence/taml/tamlCustom.cpp index 83c063a61..e45984dd4 100644 --- a/Engine/source/persistence/taml/tamlCustom.cpp +++ b/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 ); } //----------------------------------------------------------------------------- diff --git a/Engine/source/persistence/taml/tamlCustom.h b/Engine/source/persistence/taml/tamlCustom.h index 261c77dde..2f3ba857e 100644 --- a/Engine/source/persistence/taml/tamlCustom.h +++ b/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_ \ No newline at end of file +#endif // _TAML_CUSTOM_H_ diff --git a/Engine/source/persistence/taml/tamlWriteNode.h b/Engine/source/persistence/taml/tamlWriteNode.h index 5ec722045..015224589 100644 --- a/Engine/source/persistence/taml/tamlWriteNode.h +++ b/Engine/source/persistence/taml/tamlWriteNode.h @@ -54,7 +54,7 @@ public: // Allocate and copy the value. mpValue = new char[ dStrlen(pValue)+1 ]; - dStrcpy( (char *)mpValue, pValue ); + dStrcpy( (char *)mpValue, pValue, dStrlen(pValue) + 1 ); } @@ -113,4 +113,4 @@ public: TamlCustomNodes mCustomNodes; }; -#endif // _TAML_WRITE_NODE_H_ \ No newline at end of file +#endif // _TAML_WRITE_NODE_H_ diff --git a/Engine/source/platform/nativeDialogs/fileDialog.cpp b/Engine/source/platform/nativeDialogs/fileDialog.cpp index ad8bdfafb..21bdfefa3 100644 --- a/Engine/source/platform/nativeDialogs/fileDialog.cpp +++ b/Engine/source/platform/nativeDialogs/fileDialog.cpp @@ -433,7 +433,7 @@ bool FileDialog::setDefaultPath(void *object, const char *index, const char *dat // Copy and Backslash the path (Windows dialogs are VERY picky about this format) static char szPathValidate[512]; - dStrcpy(szPathValidate, data); + dStrcpy(szPathValidate, data, 512); Platform::makeFullPathName(data, szPathValidate, sizeof(szPathValidate)); //backslash( szPathValidate ); diff --git a/Engine/source/platform/platformFileIO.cpp b/Engine/source/platform/platformFileIO.cpp index 15fd9ad6d..a9ace740b 100644 --- a/Engine/source/platform/platformFileIO.cpp +++ b/Engine/source/platform/platformFileIO.cpp @@ -534,7 +534,7 @@ StringTableEntry Platform::makeRelativePathName(const char *path, const char *to // Copy the rest if(*branch) - dStrcpy(bufPtr, branch + 1); + dStrcpy(bufPtr, branch + 1, temp.size - (bufPtr - temp.ptr)); else *--bufPtr = 0; diff --git a/Engine/source/platform/platformMemory.cpp b/Engine/source/platform/platformMemory.cpp index d295a45e4..5f7aa926d 100644 --- a/Engine/source/platform/platformMemory.cpp +++ b/Engine/source/platform/platformMemory.cpp @@ -1130,7 +1130,7 @@ static void logFree(const AllocatedHeader* hdr) void enableLogging(const char* fileName) { - dStrcpy(gLogFilename, fileName); + dStrcpy(gLogFilename, fileName, 256); if (!gEnableLogging) { gEnableLogging = true; diff --git a/Engine/source/platform/platformNet.cpp b/Engine/source/platform/platformNet.cpp index a77d29474..47b655ed2 100644 --- a/Engine/source/platform/platformNet.cpp +++ b/Engine/source/platform/platformNet.cpp @@ -280,7 +280,7 @@ namespace PlatformNetState if (addressString[0] == '[') { // Must be ipv6 notation - dStrcpy(outAddress, addressString+1); + dStrcpy(outAddress, addressString+1, 256); addressString = outAddress; portString = dStrchr(outAddress, ']'); @@ -305,7 +305,7 @@ namespace PlatformNetState } else { - dStrcpy(outAddress, addressString); + dStrcpy(outAddress, addressString, 256); addressString = outAddress; // Check to see if we have multiple ":" which would indicate this is an ipv6 address @@ -546,7 +546,7 @@ static PolledSocket* addPolledSocket(NetSocket handleFd, SOCKET fd, S32 state, sock->handleFd = handleFd; sock->state = state; if (remoteAddr) - dStrcpy(sock->remoteAddr, remoteAddr); + dStrcpy(sock->remoteAddr, remoteAddr, 256); if (port != -1) sock->remotePort = port; gPolledSockets.push_back(sock); diff --git a/Engine/source/platform/platformRedBook.cpp b/Engine/source/platform/platformRedBook.cpp index d95a0eb92..82b1bae2d 100644 --- a/Engine/source/platform/platformRedBook.cpp +++ b/Engine/source/platform/platformRedBook.cpp @@ -94,7 +94,7 @@ void RedBook::setLastError(const char * error) if(!error || dStrlen(error) >= sizeof(smLastError)) setLastError("Invalid error string passed"); else - dStrcpy(smLastError, error); + dStrcpy(smLastError, error, 1024); } const char * RedBook::getLastError() diff --git a/Engine/source/platform/profiler.cpp b/Engine/source/platform/profiler.cpp index e70eb6c02..d623443ab 100644 --- a/Engine/source/platform/profiler.cpp +++ b/Engine/source/platform/profiler.cpp @@ -328,9 +328,9 @@ const char * Profiler::constructProfilePath(ProfilerData * pd) U32 mark = FrameAllocator::getWaterMark(); char * buf = (char*)FrameAllocator::alloc(len+1); - dStrcpy(buf,pd->mParent->mPath); - dStrcat(buf,connector,len); - dStrcat(buf,pd->mRoot->mName,len); + dStrcpy(buf,pd->mParent->mPath,len+1); + dStrcat(buf,connector,len+1); + dStrcat(buf,pd->mRoot->mName,len+1); const char * ret = StringTable->insert(buf); FrameAllocator::setWaterMark(mark); @@ -433,7 +433,7 @@ void Profiler::dumpToFile(const char* fileName) AssertFatal(dStrlen(fileName) < DumpFileNameLength, "Error, dump filename too long"); mDumpToFile = true; mDumpToConsole = false; - dStrcpy(mDumpFileName, fileName); + dStrcpy(mDumpFileName, fileName, DumpFileNameLength); } void Profiler::hashPop(ProfilerRootData *expected) @@ -645,11 +645,11 @@ void Profiler::dump() AssertFatal(success, "Cannot write profile dump to specified file!"); char buffer[1024]; - dStrcpy(buffer, "Profiler Data Dump:\n"); + dStrcpy(buffer, "Profiler Data Dump:\n", 1024); fws.write(dStrlen(buffer), buffer); - dStrcpy(buffer, "Ordered by non-sub total time -\n"); + dStrcpy(buffer, "Ordered by non-sub total time -\n", 1024); fws.write(dStrlen(buffer), buffer); - dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n"); + dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n", 1024); fws.write(dStrlen(buffer), buffer); for(U32 i = 0; i < rootVector.size(); i++) @@ -665,9 +665,9 @@ void Profiler::dump() rootVector[i]->mTotalTime = 0; rootVector[i]->mSubTime = 0; } - dStrcpy(buffer, "\nOrdered by non-sub total time -\n"); + dStrcpy(buffer, "\nOrdered by non-sub total time -\n", 1024); fws.write(dStrlen(buffer), buffer); - dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n"); + dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n", 1024); fws.write(dStrlen(buffer), buffer); mCurrentProfilerData->mTotalTime = endHighResolutionTimer(mCurrentProfilerData->mStartTime); diff --git a/Engine/source/platformMac/macFileIO.mm b/Engine/source/platformMac/macFileIO.mm index f11b5b052..767dbca8e 100644 --- a/Engine/source/platformMac/macFileIO.mm +++ b/Engine/source/platformMac/macFileIO.mm @@ -894,7 +894,7 @@ static bool recurseDumpDirectories(const char *basePath, const char *subPath, Ve { char child[1024]; if ( (basePath[dStrlen(basePath) - 1]) == '/') - dStrcpy (child, d->d_name); + dStrcpy (child, d->d_name, 1024); else dSprintf(child, 1024, "/%s", d->d_name); if (currentDepth < recurseDepth || recurseDepth == -1) diff --git a/Engine/source/platformWin32/minidump/winMiniDump.cpp b/Engine/source/platformWin32/minidump/winMiniDump.cpp index fbe2b96f6..267b6fc3f 100644 --- a/Engine/source/platformWin32/minidump/winMiniDump.cpp +++ b/Engine/source/platformWin32/minidump/winMiniDump.cpp @@ -144,7 +144,7 @@ INT CreateMiniDump( LPEXCEPTION_POINTERS ExceptionInfo) //copy over the pdb file char pdbName[1024]; - dStrcpy(pdbName, exeName); + dStrcpy(pdbName, exeName, 1024); dStrncat(pdbName, ".pdb", 4); dSprintf(fromFile, 2048, "%s/%s", Platform::getCurrentDirectory(), pdbName ); dSprintf(fileName, 2048, "%s/%s", crashPath, pdbName ); diff --git a/Engine/source/platformWin32/nativeDialogs/fileDialog.cpp b/Engine/source/platformWin32/nativeDialogs/fileDialog.cpp index 1d64139ee..e73bbe65b 100644 --- a/Engine/source/platformWin32/nativeDialogs/fileDialog.cpp +++ b/Engine/source/platformWin32/nativeDialogs/fileDialog.cpp @@ -142,7 +142,7 @@ static UINT_PTR CALLBACK FolderHookProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPA #ifdef UNICODE convertUTF16toUTF8(buf, filePath); #else - dStrcpy( filePath, buf ); + dStrcpy( filePath, buf, MAX_PATH ); #endif // [tom, 12/8/2006] Hack to remove files from the list because @@ -333,8 +333,8 @@ bool FileDialog::Execute() char pszFile[MAX_PATH]; char pszFilter[1024]; char pszFileTitle[MAX_PATH]; - dStrcpy( pszFile, mData.mDefaultFile ); - dStrcpy( pszFilter, mData.mFilters ); + dStrcpy( pszFile, mData.mDefaultFile, MAX_PATH ); + dStrcpy( pszFilter, mData.mFilters, 1024 ); const char* pszInitialDir = mData.mDefaultPath; const char* pszTitle = mData.mTitle; @@ -447,7 +447,7 @@ bool FileDialog::Execute() convertUTF16toUTF8DoubleNULL( (UTF16*)pszFile, (UTF8*)pszResult, sizeof(pszResult)); #else if(pszFileTitle[0] || ! ( mData.mStyle & FileDialogData::FDS_OPEN && mData.mStyle & FileDialogData::FDS_MULTIPLEFILES )) - dStrcpy(pszResult,pszFile); + dStrcpy(pszResult,pszFile,MAX_PATH); else { // [tom, 1/4/2007] pszResult is a double-NULL terminated, NULL separated list in this case so we can't just dSstrcpy() @@ -614,7 +614,7 @@ bool FileDialog::setDefaultPath( void *object, const char *index, const char *da // Copy and Backslash the path (Windows dialogs are VERY picky about this format) static char szPathValidate[512]; - dStrcpy( szPathValidate, data ); + dStrcpy( szPathValidate, data, 512 ); Platform::makeFullPathName( data,szPathValidate, sizeof(szPathValidate)); backslash( szPathValidate ); diff --git a/Engine/source/platformWin32/winDInputDevice.cpp b/Engine/source/platformWin32/winDInputDevice.cpp index 1bfed04f8..c2969c65c 100644 --- a/Engine/source/platformWin32/winDInputDevice.cpp +++ b/Engine/source/platformWin32/winDInputDevice.cpp @@ -1576,7 +1576,7 @@ const char* DInputDevice::getJoystickAxesString() } char* returnString = Con::getReturnBuffer( dStrlen( buf ) + 1 ); - dStrcpy( returnString, buf ); + dStrcpy( returnString, buf, dStrlen(buf) + 1 ); return( returnString ); } diff --git a/Engine/source/platformWin32/winFileio.cpp b/Engine/source/platformWin32/winFileio.cpp index 1fba156f5..83b7e1859 100644 --- a/Engine/source/platformWin32/winFileio.cpp +++ b/Engine/source/platformWin32/winFileio.cpp @@ -56,7 +56,7 @@ bool dFileDelete(const char * name) #ifdef UNICODE convertUTF8toUTF16N( name, buf, buf.size ); #else - dStrcpy( buf, name ); + dStrcpy( buf, name, buf.size ); #endif backslash( buf ); @@ -88,8 +88,8 @@ bool dFileRename(const char *oldName, const char *newName) convertUTF8toUTF16N( oldName, oldf, oldf.size ); convertUTF8toUTF16N( newName, newf, newf.size ); #else - dStrcpy(oldf, oldName); - dStrcpy(newf, newName); + dStrcpy(oldf, oldName, oldf.size); + dStrcpy(newf, newName, newf.size); #endif backslash(oldf); backslash(newf); @@ -106,7 +106,7 @@ bool dFileTouch(const char * name) #ifdef UNICODE convertUTF8toUTF16N( name, buf, buf.size ); #else - dStrcpy( buf, name ); + dStrcpy( buf, name, buf.size ); #endif backslash( buf ); @@ -133,8 +133,8 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) convertUTF8toUTF16N( fromName, from, from.size ); convertUTF8toUTF16N( toName, to, to.size ); #else - dStrcpy( from, fromName ); - dStrcpy( to, toName ); + dStrcpy( from, fromName, from.size ); + dStrcpy( to, toName, to.size ); #endif backslash( from ); @@ -270,7 +270,7 @@ File::FileStatus File::open(const char *filename, const AccessMode openMode) #ifdef UNICODE convertUTF8toUTF16N( filename, fname, fname.size ); #else - dStrcpy(fname, filename); + dStrcpy(fname, filename, fname.size); #endif backslash( fname ); @@ -679,7 +679,7 @@ bool Platform::getFileTimes(const char *filePath, FileTime *createTime, FileTime #ifdef UNICODE convertUTF8toUTF16N( filePath, fp, fp.size ); #else - dStrcpy( fp, filePath ); + dStrcpy( fp, filePath, fp.size ); #endif backslash( fp ); @@ -834,7 +834,7 @@ bool Platform::setCurrentDirectory(StringTableEntry newDir) #ifdef UNICODE convertUTF8toUTF16N( newDir, buf, buf.size - 1 ); #else - dStrcpy( buf, newDir ); + dStrcpy( buf, newDir, buf.size ); #endif backslash( buf ); @@ -949,7 +949,7 @@ bool Platform::isFile(const char *pFilePath) #ifdef UNICODE convertUTF8toUTF16N( pFilePath, buf, buf.size ); #else - dStrcpy( buf, pFilePath ); + dStrcpy( buf, pFilePath, buf.size ); #endif backslash( buf ); @@ -988,7 +988,7 @@ S32 Platform::getFileSize(const char *pFilePath) #ifdef UNICODE convertUTF8toUTF16N( pFilePath, buf, buf.size ); #else - dStrcpy( buf, pFilePath ); + dStrcpy( buf, pFilePath, buf.size ); #endif backslash( buf ); @@ -1025,7 +1025,7 @@ bool Platform::isDirectory(const char *pDirPath) #ifdef UNICODE convertUTF8toUTF16N( pDirPath, buf, buf.size ); #else - dStrcpy( buf, pDirPath ); + dStrcpy( buf, pDirPath, buf.size ); #endif backslash( buf ); @@ -1072,8 +1072,8 @@ bool Platform::isSubDirectory(const char *pParent, const char *pDir) convertUTF8toUTF16N( fileName, file, file.size ); convertUTF8toUTF16N( pDir, dir, dir.size ); #else - dStrcpy( file, fileName ); - dStrcpy( dir, pDir ); + dStrcpy( file, fileName, file.size ); + dStrcpy( dir, pDir, dir.size ); #endif backslash( file ); @@ -1257,7 +1257,7 @@ bool Platform::hasSubDirectory(const char *pPath) // Compose our search string - Format : ([path]/[subpath]/*) char trail = pPath[ dStrlen(pPath) - 1 ]; if( trail == '/' ) - dStrcpy( searchBuf, pPath ); + dStrcpy( searchBuf, pPath, 1024 ); else dSprintf(searchBuf, 1024, "%s/*", pPath ); diff --git a/Engine/source/platformWin32/winRedbook.cpp b/Engine/source/platformWin32/winRedbook.cpp index 309f7513a..40b030c64 100644 --- a/Engine/source/platformWin32/winRedbook.cpp +++ b/Engine/source/platformWin32/winRedbook.cpp @@ -84,7 +84,7 @@ void installRedBookDevices() { Win32RedBookDevice * device = new Win32RedBookDevice; device->mDeviceName = new char[dStrlen(str) + 1]; - dStrcpy(device->mDeviceName, str); + dStrcpy(device->mDeviceName, str, dStrlen(str) + 1); RedBook::installDevice(device); } diff --git a/Engine/source/platformWin32/winWindow.cpp b/Engine/source/platformWin32/winWindow.cpp index 74738f3b5..63fb5ea54 100644 --- a/Engine/source/platformWin32/winWindow.cpp +++ b/Engine/source/platformWin32/winWindow.cpp @@ -606,7 +606,7 @@ const char* Platform::getLoginPassword() if ( RegQueryValueEx( regKey, dT("LoginPassword"), NULL, NULL, buf, &size ) == ERROR_SUCCESS ) { returnString = Con::getReturnBuffer( size + 1 ); - dStrcpy( returnString, (const char*) buf ); + dStrcpy( returnString, (const char*) buf, size + 1 ); } RegCloseKey( regKey ); diff --git a/Engine/source/sfx/openal/sfxALProvider.cpp b/Engine/source/sfx/openal/sfxALProvider.cpp index dc6714b5a..47b2444b3 100644 --- a/Engine/source/sfx/openal/sfxALProvider.cpp +++ b/Engine/source/sfx/openal/sfxALProvider.cpp @@ -114,7 +114,7 @@ void SFXALProvider::init() dSprintf( temp, sizeof( temp ), "[EAX %d.0] %s", eax, ( mALDL->IsExtensionSupported( i, SFXALEAXRAM ) ? "EAX-RAM" : "" ) ); } else - dStrcpy( temp, "" ); + dStrcpy( temp, "", 256 ); info->driver = String::ToString( deviceFormat, major, minor, temp ); info->hasHardware = eax > 0; @@ -144,4 +144,4 @@ SFXDevice *SFXALProvider::createDevice( const String& deviceName, bool useHardwa return new SFXALDevice( this, mOpenAL, info->name, useHardware, maxBuffers ); return NULL; -} \ No newline at end of file +} diff --git a/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp b/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp index 66d746ebe..db449b49f 100644 --- a/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp @@ -142,7 +142,7 @@ void AppVertConnectorGLSL::sortVars() void AppVertConnectorGLSL::setName( char *newName ) { - dStrcpy( (char*)mName, newName ); + dStrcpy( (char*)mName, newName, 32 ); } void AppVertConnectorGLSL::reset() @@ -287,7 +287,7 @@ void VertPixelConnectorGLSL::sortVars() void VertPixelConnectorGLSL::setName( char *newName ) { - dStrcpy( (char*)mName, newName ); + dStrcpy( (char*)mName, newName, 32 ); } void VertPixelConnectorGLSL::reset() diff --git a/Engine/source/shaderGen/langElement.cpp b/Engine/source/shaderGen/langElement.cpp index 59e9a3bde..e4870bb14 100644 --- a/Engine/source/shaderGen/langElement.cpp +++ b/Engine/source/shaderGen/langElement.cpp @@ -87,7 +87,7 @@ U32 Var::texUnitCount = 0; Var::Var() { - dStrcpy( (char*)type, "float4" ); + dStrcpy( (char*)type, "float4", 32 ); structName[0] = '\0'; connectName[0] = '\0'; constSortPos = cspUninit; @@ -209,4 +209,4 @@ void MultiLine::print( Stream &stream ) { mStatementList[i]->print( stream ); } -} \ No newline at end of file +} diff --git a/Engine/source/shaderGen/shaderGen.cpp b/Engine/source/shaderGen/shaderGen.cpp index a182588d5..6b19ba0f5 100644 --- a/Engine/source/shaderGen/shaderGen.cpp +++ b/Engine/source/shaderGen/shaderGen.cpp @@ -153,8 +153,8 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData, dSprintf( vertShaderName, sizeof(vertShaderName), "shadergen:/%s_V.%s", cacheName, mFileEnding.c_str() ); dSprintf( pixShaderName, sizeof(pixShaderName), "shadergen:/%s_P.%s", cacheName, mFileEnding.c_str() ); - dStrcpy( vertFile, vertShaderName ); - dStrcpy( pixFile, pixShaderName ); + dStrcpy( vertFile, vertShaderName, 256 ); + dStrcpy( pixFile, pixShaderName, 256 ); // this needs to change - need to optimize down to ps v.1.1 *pixVersion = GFX->getPixelShaderVersion(); diff --git a/Engine/source/sim/actionMap.cpp b/Engine/source/sim/actionMap.cpp index 4e5f6948a..948d066c1 100644 --- a/Engine/source/sim/actionMap.cpp +++ b/Engine/source/sim/actionMap.cpp @@ -245,7 +245,7 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const else { // IMPORTANT -- do NOT change the following line, it identifies the file as an input map file - dStrcpy( lineBuffer, "// Torque Input Map File\n" ); + dStrcpy( lineBuffer, "// Torque Input Map File\n", 1024 ); iostrm->write( dStrlen( lineBuffer ), lineBuffer ); } @@ -453,7 +453,7 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const bool ActionMap::createEventDescriptor(const char* pEventString, EventDescriptor* pDescriptor) { char copyBuffer[256]; - dStrcpy(copyBuffer, pEventString); + dStrcpy(copyBuffer, pEventString, 256); // Do we have modifiers? char* pSpace = dStrchr(copyBuffer, ' '); @@ -909,7 +909,7 @@ const char* ActionMap::getDeadZone( const char* device, const char* action ) char buf[64]; dSprintf( buf, sizeof( buf ), "%g %g", mapNode->deadZoneBegin, mapNode->deadZoneEnd ); char* returnString = Con::getReturnBuffer( dStrlen( buf ) + 1 ); - dStrcpy( returnString, buf ); + dStrcpy( returnString, buf, dStrlen(buf) + 1 ); return( returnString ); } else @@ -995,7 +995,7 @@ bool ActionMap::getDeviceName(const U32 deviceType, const U32 deviceInstance, ch { switch (deviceType) { case KeyboardDeviceType: - dStrcpy(buffer, "keyboard"); + dStrcpy(buffer, "keyboard", 16); break; case MouseDeviceType: @@ -1135,7 +1135,7 @@ bool ActionMap::getKeyString(const U32 action, char* buffer) for (U32 i = 0; gAsciiMap[i].asciiCode != 0xFFFF; i++) { if (gAsciiMap[i].asciiCode == asciiCode) { - dStrcpy(buffer, gAsciiMap[i].pDescription); + dStrcpy(buffer, gAsciiMap[i].pDescription, 16); return true; } } @@ -1166,7 +1166,7 @@ bool ActionMap::getKeyString(const U32 action, char* buffer) const char* desc = INPUTMGR->findVirtualMapDescFromCode(action); if(desc) { - dStrcpy(buffer, desc); + dStrcpy(buffer, desc, 16); return true; } } diff --git a/Engine/source/sim/netDownload.cpp b/Engine/source/sim/netDownload.cpp index 00fc6f0fc..b523ef0ad 100644 --- a/Engine/source/sim/netDownload.cpp +++ b/Engine/source/sim/netDownload.cpp @@ -53,7 +53,7 @@ public: for(U32 i = 0; i < nameCount; i++) { - dStrcpy(mFileNames[i], (*nameList)[i]); + dStrcpy(mFileNames[i], (*nameList)[i], 256); //Con::printf("Sending request for file %s", mFileNames[i]); } } diff --git a/Engine/source/sim/netStringTable.cpp b/Engine/source/sim/netStringTable.cpp index d1a25e826..c21377885 100644 --- a/Engine/source/sim/netStringTable.cpp +++ b/Engine/source/sim/netStringTable.cpp @@ -97,7 +97,7 @@ U32 NetStringTable::addString(const char *string) } table[e].refCount++; table[e].string = (char *) allocator->alloc(dStrlen(string) + 1); - dStrcpy(table[e].string, string); + dStrcpy(table[e].string, string, dStrlen(string) + 1); table[e].next = hashTable[bucket]; hashTable[bucket] = e; table[e].link = firstValid; @@ -179,7 +179,7 @@ void NetStringTable::repack() table[walk].string = (char *) newAllocator->alloc(dStrlen(prevStr) + 1); - dStrcpy(table[walk].string, prevStr); + dStrcpy(table[walk].string, prevStr, dStrlen(prevStr) + 1); } delete allocator; allocator = newAllocator; diff --git a/Engine/source/terrain/terrData.cpp b/Engine/source/terrain/terrData.cpp index 8665fa9f4..37f523356 100644 --- a/Engine/source/terrain/terrData.cpp +++ b/Engine/source/terrain/terrData.cpp @@ -1303,7 +1303,7 @@ DefineEngineMethod( TerrainBlock, save, bool, ( const char* fileName),, "@return True if file save was successful, false otherwise") { char filename[256]; - dStrcpy(filename,fileName); + dStrcpy(filename,fileName,256); char *ext = dStrrchr(filename, '.'); if (!ext || dStricmp(ext, ".ter") != 0) dStrcat(filename, ".ter", 256); @@ -1313,7 +1313,7 @@ DefineEngineMethod( TerrainBlock, save, bool, ( const char* fileName),, //ConsoleMethod(TerrainBlock, save, bool, 3, 3, "(string fileName) - saves the terrain block's terrain file to the specified file name.") //{ // char filename[256]; -// dStrcpy(filename,argv[2]); +// dStrcpy(filename,argv[2],256); // char *ext = dStrrchr(filename, '.'); // if (!ext || dStricmp(ext, ".ter") != 0) // dStrcat(filename, ".ter", 256); diff --git a/Engine/source/util/messaging/eventManager.cpp b/Engine/source/util/messaging/eventManager.cpp index f39bf13b0..5463e1efc 100644 --- a/Engine/source/util/messaging/eventManager.cpp +++ b/Engine/source/util/messaging/eventManager.cpp @@ -289,7 +289,7 @@ bool EventManager::subscribe(SimObject *callbackObj, const char* event, const ch else { cb = new char[dStrlen(callback) + 1]; - dStrcpy(cb, callback); + dStrcpy(cb, callback, dStrlen(callback) + 1); } // Create the subscriber object. diff --git a/Engine/source/util/undo.cpp b/Engine/source/util/undo.cpp index fd23033fa..11334a793 100644 --- a/Engine/source/util/undo.cpp +++ b/Engine/source/util/undo.cpp @@ -546,7 +546,7 @@ DefineConsoleMethod(UndoManager, getNextUndoName, const char *, (),, "UndoManage if(!name) return NULL; char *ret = Con::getReturnBuffer(dStrlen(name) + 1); - dStrcpy(ret, name); + dStrcpy(ret, name, dStrlen(name) + 1); return ret; } @@ -557,7 +557,7 @@ DefineConsoleMethod(UndoManager, getNextRedoName, const char *, (),, "UndoManage if(!name) return NULL; char *ret = Con::getReturnBuffer(dStrlen(name) + 1); - dStrcpy(ret, name); + dStrcpy(ret, name, dStrlen(name) + 1); return ret; } From c4533b4dc4d15bd594b3d73f013009d05468fd04 Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Tue, 6 Mar 2018 02:35:46 -0500 Subject: [PATCH 15/26] Actual buffer overflow bug found because of these fixes --- Engine/source/console/fileSystemFunctions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/source/console/fileSystemFunctions.cpp b/Engine/source/console/fileSystemFunctions.cpp index ec2d9c17d..0fdafec85 100644 --- a/Engine/source/console/fileSystemFunctions.cpp +++ b/Engine/source/console/fileSystemFunctions.cpp @@ -643,8 +643,8 @@ DefineEngineFunction(fileName, String, ( const char* fileName ),, name = szPathCopy; else name++; - char *ret = Con::getReturnBuffer(dStrlen(name)); - dStrcpy(ret, name, dStrlen(name)); + char *ret = Con::getReturnBuffer(dStrlen(name) + 1); + dStrcpy(ret, name, dStrlen(name) + 1); return ret; } From 396fe5b0adf68790a85d5a3bd72e48d937f2bafd Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Tue, 6 Mar 2018 02:37:42 -0500 Subject: [PATCH 16/26] Cleaning up the checks --- Engine/source/core/strings/stringFunctions.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Engine/source/core/strings/stringFunctions.h b/Engine/source/core/strings/stringFunctions.h index e4307a092..c2058c119 100644 --- a/Engine/source/core/strings/stringFunctions.h +++ b/Engine/source/core/strings/stringFunctions.h @@ -47,21 +47,23 @@ #endif // defined(TORQUE_OS_WIN) -#define DEBUG_CHECK_OVERFLOW 1 +#define DEBUG_CHECK_STRING_OVERFLOW //------------------------------------------------------------------------------ // standard string functions [defined in platformString.cpp] +#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 inline char *dStrcat(char *dst, const char *src, dsize_t len) { -#ifdef DEBUG_CHECK_OVERFLOW +#ifdef DEBUG_CHECK_STRING_OVERFLOW if (strlen(src) >= len) { AssertWarn(false, "dStrcat out of range"); } @@ -99,16 +101,18 @@ 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 len) { -#ifdef DEBUG_CHECK_OVERFLOW +#ifdef DEBUG_CHECK_STRING_OVERFLOW if (strlen(src) >= len) { AssertWarn(false, "dStrcpy out of range"); } From e6e97e660cedb2fcc5f36fbe2c3c3f9d95f73349 Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Wed, 7 Mar 2018 00:44:28 -0500 Subject: [PATCH 17/26] Missed a couple +1s here and there --- Engine/source/afx/arcaneFX.cpp | 6 +++--- Engine/source/app/badWordFilter.cpp | 2 +- Engine/source/console/SimXMLDocument.cpp | 4 ++-- Engine/source/console/console.cpp | 4 ++-- Engine/source/console/persistenceManager.cpp | 6 +++--- Engine/source/gui/editor/guiEditCtrl.cpp | 4 ++-- Engine/source/platformWin32/winFileio.cpp | 9 ++++----- 7 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Engine/source/afx/arcaneFX.cpp b/Engine/source/afx/arcaneFX.cpp index 8ec0e9760..cec0c870a 100644 --- a/Engine/source/afx/arcaneFX.cpp +++ b/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], len); + 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], len); + 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], len); + dStrcat(ret, argv[i], len + 1); Con::errorf("%s -- [%s]", ret, argv[1].getStringValue()); ret[0] = 0; diff --git a/Engine/source/app/badWordFilter.cpp b/Engine/source/app/badWordFilter.cpp index d789bc1c4..0a13a9c29 100644 --- a/Engine/source/app/badWordFilter.cpp +++ b/Engine/source/app/badWordFilter.cpp @@ -287,7 +287,7 @@ DefineEngineFunction(filterString, const char *, (const char* baseString, const replaceStr = gBadWordFilter->getDefaultReplaceStr(); char *ret = Con::getReturnBuffer(dStrlen(baseString) + 1); - dStrcpy(ret, baseString, dStrlen(baseString)); + dStrcpy(ret, baseString, dStrlen(baseString) + 1); gBadWordFilter->filterString(ret, replaceStr); return ret; } diff --git a/Engine/source/console/SimXMLDocument.cpp b/Engine/source/console/SimXMLDocument.cpp index 4071ae138..156533503 100644 --- a/Engine/source/console/SimXMLDocument.cpp +++ b/Engine/source/console/SimXMLDocument.cpp @@ -833,7 +833,7 @@ void SimXMLDocument::setObjectAttributes(const char* objectID) continue; FrameTemp valCopy( dStrlen( val ) + 1 ); - dStrcpy( (char *)valCopy, val, dStrlen(val) + 1 ); + 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 valCopy( dStrlen( val ) + 1 ); - // dStrcpy( (char *)valCopy, val, dStrlen(val) + 1 ); + // dStrcpy( (char *)valCopy, val, valCopy.size() ); // if (!pObject->writeField(itr->pFieldname, valCopy)) // continue; diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index fd5d343d2..be472f197 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -2176,8 +2176,8 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor } // Format the output path. - dStrcat(pathBuffer, "/", sizeof(pathBuffer) - 1 - strlen(pathBuffer)); - dStrcat(pathBuffer, pSrc, sizeof(pathBuffer) - 1 - strlen(pathBuffer)); + dStrncat(pathBuffer, "/", sizeof(pathBuffer) - 1 - strlen(pathBuffer)); + dStrncat(pathBuffer, pSrc, sizeof(pathBuffer) - 1 - strlen(pathBuffer)); // Are we ensuring the trailing slash? if (ensureTrailingSlash) diff --git a/Engine/source/console/persistenceManager.cpp b/Engine/source/console/persistenceManager.cpp index df2dd8b01..56812cd4b 100644 --- a/Engine/source/console/persistenceManager.cpp +++ b/Engine/source/console/persistenceManager.cpp @@ -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, newLineLen); + dStrcat(newLine, preString, newLineLen + 1); if ( newValue ) - dStrcat(newLine, newValue, newLineLen); - dStrcat(newLine, postString, newLineLen); + dStrcat(newLine, newValue, newLineLen + 1); + dStrcat(newLine, postString, newLineLen + 1); // Clear our existing line if (mLineBuffer[lineNumber]) diff --git a/Engine/source/gui/editor/guiEditCtrl.cpp b/Engine/source/gui/editor/guiEditCtrl.cpp index 571d1df84..bf20e8568 100644 --- a/Engine/source/gui/editor/guiEditCtrl.cpp +++ b/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(), str.length() ); + char* buffer = Con::getReturnBuffer( str.size() ); + dStrcpy( buffer, str.c_str(), str.size() ); return buffer; } diff --git a/Engine/source/platformWin32/winFileio.cpp b/Engine/source/platformWin32/winFileio.cpp index 83b7e1859..3e1974ae4 100644 --- a/Engine/source/platformWin32/winFileio.cpp +++ b/Engine/source/platformWin32/winFileio.cpp @@ -158,8 +158,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) Platform::clearExcludedDirectories(); - S32 tempBufSize = to.size * 3 + MAX_PATH * 3; - TempAlloc< char > tempBuf( tempBufSize ); + TempAlloc< char > tempBuf( to.size * 3 + MAX_PATH * 3 ); // Create all the directories. for (S32 i = 0; i < directoryInfo.size(); i++) @@ -169,7 +168,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) char* toDir = tempBuf; Platform::makeFullPathName(fromDir + dStrlen(fromName) + (dStricmp(fromDir, fromName) ? 1 : 0), tempBuf, tempBuf.size, toName); if(*(toDir + dStrlen(toDir) - 1) != '/') - dStrcat(toDir, "/", tempBufSize); + dStrcat(toDir, "/", tempBuf.size); forwardslash(toDir); if (!Platform::createPath(toDir)) @@ -192,8 +191,8 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) char* toFile = tempBuf; Platform::makeFullPathName(fileInfo[i].pFullPath + dStrlen(fromName) + (dStricmp(fileInfo[i].pFullPath, fromName) ? 1 : 0), tempBuf, tempBuf.size, toName); - dStrcat(toFile, "/", tempBufSize); - dStrcat(toFile, fileInfo[i].pFileName, tempBufSize); + dStrcat(toFile, "/", tempBuf.size); + dStrcat(toFile, fileInfo[i].pFileName, tempBuf.size); backslash(fromFile); backslash(toFile); From dce7f5f6b3425400641e89890b0b53a59660d2c1 Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Wed, 7 Mar 2018 00:49:46 -0500 Subject: [PATCH 18/26] Engine was also using raw strcat/strcpy --- Engine/source/cinterface/cinterface.cpp | 4 ++-- Engine/source/persistence/taml/fsTinyXml.cpp | 2 +- Engine/source/persistence/taml/xml/tamlXmlParser.cpp | 2 +- Engine/source/platform/platformCPUCount.cpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Engine/source/cinterface/cinterface.cpp b/Engine/source/cinterface/cinterface.cpp index f195cd7e7..4f6f1900c 100644 --- a/Engine/source/cinterface/cinterface.cpp +++ b/Engine/source/cinterface/cinterface.cpp @@ -182,8 +182,8 @@ extern "C" { void torque_setexecutablepath(const char* directory) { - gExecutablePath = new char[strlen(directory)+1]; - strcpy(gExecutablePath, directory); + gExecutablePath = new char[dStrlen(directory)+1]; + dStrcpy(gExecutablePath, directory, dStrlen(directory)+1); } // set Torque 3D into web deployment mode (disable fullscreen exlusive mode, etc) diff --git a/Engine/source/persistence/taml/fsTinyXml.cpp b/Engine/source/persistence/taml/fsTinyXml.cpp index 441169742..9fdf3f812 100644 --- a/Engine/source/persistence/taml/fsTinyXml.cpp +++ b/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 diff --git a/Engine/source/persistence/taml/xml/tamlXmlParser.cpp b/Engine/source/persistence/taml/xml/tamlXmlParser.cpp index b479fa07e..6ba33dd98 100644 --- a/Engine/source/persistence/taml/xml/tamlXmlParser.cpp +++ b/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 diff --git a/Engine/source/platform/platformCPUCount.cpp b/Engine/source/platform/platformCPUCount.cpp index fc066f75d..a3fe99d67 100644 --- a/Engine/source/platform/platformCPUCount.cpp +++ b/Engine/source/platform/platformCPUCount.cpp @@ -523,7 +523,7 @@ next: tblPkgID[j] = apicID & PackageIDMask; sprintf(tmp," AffinityMask = %d; Initial APIC = %d; Physical ID = %d, Core ID = %d, SMT ID = %d\n", dwAffinityMask, apicID, tblPkgID[j], tblCoreID[j], tblSMTID[j]); - strcat(g_s3Levels, tmp); + dStrcat(g_s3Levels, tmp, 2048); numLPEnabled ++; // Number of available logical processors in the system. @@ -654,4 +654,4 @@ next: } // namespace CPUInfo #endif -#endif \ No newline at end of file +#endif From d9a723d5333947bbdb6e47fc64dc65471b07b2b7 Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Wed, 7 Mar 2018 01:13:56 -0500 Subject: [PATCH 19/26] More cats and cpys in files that xcode doesn't see --- Engine/source/afx/ce/afxAudioBank.cpp | 2 +- Engine/source/console/CMDscan.l | 8 ++++---- Engine/source/console/consoleXMLExport.cpp | 4 ++-- Engine/source/core/frameAllocator.h | 2 +- Engine/source/core/util/zip/test/zipTestWrite.cpp | 4 ++-- Engine/source/gui/controls/guiPopUpCtrlEx.cpp | 12 ++++++------ .../platform/input/leapMotion/leapMotionDevice.cpp | 2 +- .../platform/input/oculusVR/oculusVRDevice.cpp | 2 +- .../source/platform/input/openVR/openVRProvider.cpp | 2 +- .../platform/input/razerHydra/razerHydraDevice.cpp | 2 +- Engine/source/platformX86UNIX/x86UNIXFileio.cpp | 10 +++++----- .../source/platformX86UNIX/x86UNIXInput.client.cpp | 2 +- Engine/source/platformX86UNIX/x86UNIXNet.cpp | 6 +++--- .../platformX86UNIX/x86UNIXOGLVideo.client.cpp | 2 +- Engine/source/platformX86UNIX/x86UNIXRedbook.cpp | 2 +- Engine/source/shaderGen/HLSL/shaderCompHLSL.cpp | 2 +- Engine/source/sim/actionMap.cpp | 2 +- Engine/source/sim/connectionStringTable.cpp | 2 +- Engine/source/sim/netObject.h | 8 ++++---- Engine/source/sqlite/SQLiteObject.cpp | 6 +++--- Engine/source/testing/unitTesting.cpp | 4 ++-- 21 files changed, 43 insertions(+), 43 deletions(-) diff --git a/Engine/source/afx/ce/afxAudioBank.cpp b/Engine/source/afx/ce/afxAudioBank.cpp index 2aa148474..82537419d 100644 --- a/Engine/source/afx/ce/afxAudioBank.cpp +++ b/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); */ diff --git a/Engine/source/console/CMDscan.l b/Engine/source/console/CMDscan.l index d9b92b6d2..c4bdc1bf3 100644 --- a/Engine/source/console/CMDscan.l +++ b/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,10 @@ 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 ); - + dStrcpy( buffer, CMDtext + 1, dStrlen( CMDtext ) ); + CMDlval.str = MakeToken< char* >( buffer, lineIndex ); return ret; } diff --git a/Engine/source/console/consoleXMLExport.cpp b/Engine/source/console/consoleXMLExport.cpp index 953a016cf..79e302595 100644 --- a/Engine/source/console/consoleXMLExport.cpp +++ b/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; } diff --git a/Engine/source/core/frameAllocator.h b/Engine/source/core/frameAllocator.h index 86884085c..2e03e6fc2 100644 --- a/Engine/source/core/frameAllocator.h +++ b/Engine/source/core/frameAllocator.h @@ -185,7 +185,7 @@ public: /// the FrameAllocator. For example: /// @code /// FrameTemp 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 ); diff --git a/Engine/source/core/util/zip/test/zipTestWrite.cpp b/Engine/source/core/util/zip/test/zipTestWrite.cpp index 889cf6948..d23f9a657 100644 --- a/Engine/source/core/util/zip/test/zipTestWrite.cpp +++ b/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); diff --git a/Engine/source/gui/controls/guiPopUpCtrlEx.cpp b/Engine/source/gui/controls/guiPopUpCtrlEx.cpp index fc7811e69..2c8f5342a 100644 --- a/Engine/source/gui/controls/guiPopUpCtrlEx.cpp +++ b/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" ); diff --git a/Engine/source/platform/input/leapMotion/leapMotionDevice.cpp b/Engine/source/platform/input/leapMotion/leapMotionDevice.cpp index 5e4aef681..9bbb3eaaf 100644 --- a/Engine/source/platform/input/leapMotion/leapMotionDevice.cpp +++ b/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; diff --git a/Engine/source/platform/input/oculusVR/oculusVRDevice.cpp b/Engine/source/platform/input/oculusVR/oculusVRDevice.cpp index 229bc0429..e2ffb411a 100644 --- a/Engine/source/platform/input/oculusVR/oculusVRDevice.cpp +++ b/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(); // diff --git a/Engine/source/platform/input/openVR/openVRProvider.cpp b/Engine/source/platform/input/openVR/openVRProvider.cpp index 9fa31e4cc..53cc228f5 100644 --- a/Engine/source/platform/input/openVR/openVRProvider.cpp +++ b/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); diff --git a/Engine/source/platform/input/razerHydra/razerHydraDevice.cpp b/Engine/source/platform/input/razerHydra/razerHydraDevice.cpp index 8a36bd9d6..e2d87129d 100644 --- a/Engine/source/platform/input/razerHydra/razerHydraDevice.cpp +++ b/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(); // diff --git a/Engine/source/platformX86UNIX/x86UNIXFileio.cpp b/Engine/source/platformX86UNIX/x86UNIXFileio.cpp index 6e51b85e1..40f5fedae 100644 --- a/Engine/source/platformX86UNIX/x86UNIXFileio.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXFileio.cpp @@ -211,7 +211,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) dStrncpy(pathEl, currChar, pathElLen); pathEl[pathElLen] = '\0'; dStrncpy(testPath, tempBuf, MaxPath); - dStrcat(testPath, pathEl); + dStrcat(testPath, pathEl, MaxPath); if (stat(testPath, &filestat) != -1) { dStrncpy(tempBuf, testPath, MaxPath); @@ -226,7 +226,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) if (dStricmp(pathEl, ent->d_name) == 0) { foundMatch = true; - dStrcat(tempBuf, ent->d_name); + dStrcat(tempBuf, ent->d_name, MaxPath); break; } } @@ -238,7 +238,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) } if (*termChar == '/') { - dStrcat(tempBuf, "/"); + dStrcat(tempBuf, "/", MaxPath); termChar++; currChar = termChar; } @@ -935,7 +935,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) TempAlloc< UTF8 > buf( dStrlen( newDir ) + 2 ); - dStrcpy( buf, newDir ); + dStrcpy( buf, newDir, buf.size ); ForwardSlash( buf ); return chdir( buf ) == 0; @@ -1267,7 +1267,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) { char child[1024]; if ( (basePath[dStrlen(basePath) - 1]) == '/') - dStrcpy (child, d->d_name); + dStrcpy (child, d->d_name, 1024); else dSprintf(child, 1024, "/%s", d->d_name); if (currentDepth < recurseDepth || recurseDepth == -1) diff --git a/Engine/source/platformX86UNIX/x86UNIXInput.client.cpp b/Engine/source/platformX86UNIX/x86UNIXInput.client.cpp index 37e3ee179..2776601a7 100644 --- a/Engine/source/platformX86UNIX/x86UNIXInput.client.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXInput.client.cpp @@ -554,7 +554,7 @@ bool XClipboard::setClipboard(const char *text) checkTDataSize(len); // copy the data into the storage buffer - dStrcpy(mTData, text); + dStrcpy(mTData, text, mTDataSize); // tell X that we own the clipboard. (we'll get events // if an app tries to paste) diff --git a/Engine/source/platformX86UNIX/x86UNIXNet.cpp b/Engine/source/platformX86UNIX/x86UNIXNet.cpp index e186b8f8a..2cfb81521 100644 --- a/Engine/source/platformX86UNIX/x86UNIXNet.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXNet.cpp @@ -97,7 +97,7 @@ static Socket* addPolledSocket(NetSocket& fd, S32 state, sock->fd = fd; sock->state = state; if (remoteAddr) - dStrcpy(sock->remoteAddr, remoteAddr); + dStrcpy(sock->remoteAddr, remoteAddr, 256); if (port != -1) sock->remotePort = port; gPolledSockets.push_back(sock); @@ -242,7 +242,7 @@ NetSocket Net::openConnectTo(const char *addressString) if(!dStrnicmp(addressString, "ip:", 3)) addressString += 3; // eat off the ip: char remoteAddr[256]; - dStrcpy(remoteAddr, addressString); + dStrcpy(remoteAddr, addressString, 256); char *portString = dStrchr(remoteAddr, ':'); @@ -814,7 +814,7 @@ bool Net::stringToAddress(const char *addressString, NetAddress *address) if(strlen(addressString) > 255) return false; - dStrcpy(remoteAddr, addressString); + dStrcpy(remoteAddr, addressString, 256); char *portString = dStrchr(remoteAddr, ':'); if(portString) diff --git a/Engine/source/platformX86UNIX/x86UNIXOGLVideo.client.cpp b/Engine/source/platformX86UNIX/x86UNIXOGLVideo.client.cpp index 16f906f69..384aade9e 100644 --- a/Engine/source/platformX86UNIX/x86UNIXOGLVideo.client.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXOGLVideo.client.cpp @@ -41,7 +41,7 @@ bool InitOpenGL() // Get the video settings from the prefs: const char* resString = Con::getVariable( "$pref::Video::resolution" ); char* tempBuf = new char[dStrlen( resString ) + 1]; - dStrcpy( tempBuf, resString ); + dStrcpy( tempBuf, resString, dStrlen(resString) + 1 ); char* temp = dStrtok( tempBuf, " x\0" ); U32 width = ( temp ? dAtoi( temp ) : 800 ); temp = dStrtok( NULL, " x\0" ); diff --git a/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp b/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp index 65741218f..3484a56ce 100644 --- a/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp @@ -102,7 +102,7 @@ void UnixRedBookDevice::setDeviceInfo(S32 deviceId, const char *deviceName) #if !defined(__FreeBSD__) mDeviceId = deviceId; mDeviceName = new char[dStrlen(deviceName) + 1]; - dStrcpy(mDeviceName, deviceName); + dStrcpy(mDeviceName, deviceName, dStrlen(deviceName) + 1); #endif // !defined(__FreeBSD__) } diff --git a/Engine/source/shaderGen/HLSL/shaderCompHLSL.cpp b/Engine/source/shaderGen/HLSL/shaderCompHLSL.cpp index b01419a8b..66c23d353 100644 --- a/Engine/source/shaderGen/HLSL/shaderCompHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/shaderCompHLSL.cpp @@ -232,7 +232,7 @@ void ShaderConnectorHLSL::sortVars() void ShaderConnectorHLSL::setName( char *newName ) { - dStrcpy( (char*)mName, newName ); + dStrcpy( (char*)mName, newName, 32 ); } void ShaderConnectorHLSL::reset() diff --git a/Engine/source/sim/actionMap.cpp b/Engine/source/sim/actionMap.cpp index 948d066c1..1d0fbe8b5 100644 --- a/Engine/source/sim/actionMap.cpp +++ b/Engine/source/sim/actionMap.cpp @@ -1159,7 +1159,7 @@ bool ActionMap::getKeyString(const U32 action, char* buffer) } //for (U32 i = 0; gVirtualMap[i].code != 0xFFFFFFFF; i++) { // if (gVirtualMap[i].code == action) { - // dStrcpy(buffer, gVirtualMap[i].pDescription); + // dStrcpy(buffer, gVirtualMap[i].pDescription, 16); // return true; // } //} diff --git a/Engine/source/sim/connectionStringTable.cpp b/Engine/source/sim/connectionStringTable.cpp index dddd935b2..c3fa4dff6 100644 --- a/Engine/source/sim/connectionStringTable.cpp +++ b/Engine/source/sim/connectionStringTable.cpp @@ -71,7 +71,7 @@ public: static char buffer[512]; dSprintf(buffer, sizeof(buffer), "%s - \"", getClassName()); expandEscape(buffer + dStrlen(buffer), mString.getString()); - dStrcat(buffer, "\""); + dStrcat(buffer, "\"", 512); return buffer; } #endif diff --git a/Engine/source/sim/netObject.h b/Engine/source/sim/netObject.h index 7ea1283c4..bbc913c26 100644 --- a/Engine/source/sim/netObject.h +++ b/Engine/source/sim/netObject.h @@ -132,8 +132,8 @@ struct GhostInfo; /// // the ScopeAlways flag indicates that the object is always scoped /// // on all active connections. /// mNetFlags.set(ScopeAlways | Ghostable); -/// dStrcpy(message1, "Hello World 1!"); -/// dStrcpy(message2, "Hello World 2!"); +/// dStrcpy(message1, "Hello World 1!", bufLen); +/// dStrcpy(message2, "Hello World 2!", bufLen); /// } /// @endcode /// @@ -187,12 +187,12 @@ struct GhostInfo; /// void setMessage1(const char *msg) /// { /// setMaskBits(Message1Mask); -/// dStrcpy(message1, msg); +/// dStrcpy(message1, msg, bufLen); /// } /// void setMessage2(const char *msg) /// { /// setMaskBits(Message2Mask); -/// dStrcpy(message2, msg); +/// dStrcpy(message2, msg, bufLen); /// } /// @endcode /// diff --git a/Engine/source/sqlite/SQLiteObject.cpp b/Engine/source/sqlite/SQLiteObject.cpp index 7fe06de5f..a2900ab30 100644 --- a/Engine/source/sqlite/SQLiteObject.cpp +++ b/Engine/source/sqlite/SQLiteObject.cpp @@ -158,18 +158,18 @@ S32 Callback(void *pArg, S32 argc, char **argv, char **columnNames) // DBEUG CODE // Con::printf("%s = %s\n", columnNames[i], argv[i] ? argv[i] : "NULL"); name = new char[dStrlen(columnNames[i]) + 1]; - dStrcpy(name, columnNames[i]); + dStrcpy(name, columnNames[i], dStrlen(columnNames[i]) + 1); pRow->vColumnNames.push_back(name); if (argv[i]) { value = new char[dStrlen(argv[i]) + 1]; - dStrcpy(value, argv[i]); + dStrcpy(value, argv[i], dStrlen(argv[i]) + 1); pRow->vColumnValues.push_back(value); } else { value = new char[10]; - dStrcpy(value, "NULL"); + dStrcpy(value, "NULL", 10); pRow->vColumnValues.push_back(value); } } diff --git a/Engine/source/testing/unitTesting.cpp b/Engine/source/testing/unitTesting.cpp index 2724bf637..a86a28eb3 100644 --- a/Engine/source/testing/unitTesting.cpp +++ b/Engine/source/testing/unitTesting.cpp @@ -99,8 +99,8 @@ DefineConsoleFunction( runAllUnitTests, int, (const char* testSpecs), (""), testArgc = 2; testArgv = new char*[2]; testArgv[0] = NULL; // Program name is unused by googletest. - testArgv[1] = new char[specs.length()+1]; - dStrcpy(testArgv[1], specs); + testArgv[1] = new char[specs.size()]; + dStrcpy(testArgv[1], specs, specs.size()); } // Initialize Google Test. From e01272d72d977f9844194c278ec4976ccadc7fef Mon Sep 17 00:00:00 2001 From: Areloch Date: Wed, 7 Mar 2018 01:30:44 -0600 Subject: [PATCH 20/26] Missed a cleanup line. --- Engine/source/T3D/convexShape.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Engine/source/T3D/convexShape.cpp b/Engine/source/T3D/convexShape.cpp index d73d387bd..bc23798d0 100644 --- a/Engine/source/T3D/convexShape.cpp +++ b/Engine/source/T3D/convexShape.cpp @@ -733,7 +733,6 @@ bool ConvexShape::buildExportPolyList(ColladaUtils::ExportData* exportData, cons meshData->originatingObject = this; meshData->meshTransform = mObjToWorld; meshData->scale = mObjScale; - meshData->fillWithSingleDetail = true; meshData->meshDetailLevels.increment(); From a46cadc4876cccfa6c855591e7ce387cff484a43 Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Wed, 7 Mar 2018 03:58:28 -0500 Subject: [PATCH 21/26] Let dStrncat use strncat because it's probably set up for that --- Engine/source/core/strings/stringFunctions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/core/strings/stringFunctions.h b/Engine/source/core/strings/stringFunctions.h index c2058c119..c296da871 100644 --- a/Engine/source/core/strings/stringFunctions.h +++ b/Engine/source/core/strings/stringFunctions.h @@ -73,7 +73,7 @@ inline char *dStrcat(char *dst, const char *src, dsize_t len) inline char *dStrncat(char *dst, const char *src, dsize_t len) { - return dStrcat(dst, src, len); + return strncat(dst, src, len); } inline S32 dStrcmp(const char *str1, const char *str2) From a061923c1ed6f5912b0d46d72e35df2b253d5ea9 Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Thu, 8 Mar 2018 00:45:24 -0500 Subject: [PATCH 22/26] Better to use strlcat and strlcpy and move them to the cpp file. Provided an implementation for platforms that don't support them (macOS only currently) --- .../source/core/strings/stringFunctions.cpp | 61 +++++++++++++++++++ Engine/source/core/strings/stringFunctions.h | 32 +++++----- 2 files changed, 77 insertions(+), 16 deletions(-) diff --git a/Engine/source/core/strings/stringFunctions.cpp b/Engine/source/core/strings/stringFunctions.cpp index 93db4fd47..668c9d649 100644 --- a/Engine/source/core/strings/stringFunctions.cpp +++ b/Engine/source/core/strings/stringFunctions.cpp @@ -381,6 +381,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 diff --git a/Engine/source/core/strings/stringFunctions.h b/Engine/source/core/strings/stringFunctions.h index c296da871..918273423 100644 --- a/Engine/source/core/strings/stringFunctions.h +++ b/Engine/source/core/strings/stringFunctions.h @@ -47,11 +47,14 @@ #endif // defined(TORQUE_OS_WIN) -#define DEBUG_CHECK_STRING_OVERFLOW - //------------------------------------------------------------------------------ // 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) @@ -61,14 +64,15 @@ inline char *dStrcat(char *dst, const char *src) } #endif -inline char *dStrcat(char *dst, const char *src, dsize_t len) +/// 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) { -#ifdef DEBUG_CHECK_STRING_OVERFLOW - if (strlen(src) >= len) { - AssertWarn(false, "dStrcat out of range"); - } -#endif - return strncat(dst,src,len - 1); //Safety because strncat copies at most len+1 characters + dStrlcat(dst, src, dstSize); + return dst; } inline char *dStrncat(char *dst, const char *src, dsize_t len) @@ -110,14 +114,10 @@ inline char *dStrcpy(char *dst, const char *src) } #endif -inline char *dStrcpy(char *dst, const char *src, dsize_t len) +inline char *dStrcpy(char *dst, const char *src, dsize_t dstSize) { -#ifdef DEBUG_CHECK_STRING_OVERFLOW - if (strlen(src) >= len) { - AssertWarn(false, "dStrcpy out of range"); - } -#endif - return strncpy(dst,src,len); + dStrlcpy(dst, src, dstSize); + return dst; } inline char *dStrncpy(char *dst, const char *src, dsize_t len) From 34b2d91e899df10212186d58583507bf20a78737 Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Thu, 8 Mar 2018 00:45:43 -0500 Subject: [PATCH 23/26] Speaking of badly sized mac things --- Engine/source/platform/types.mac.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Engine/source/platform/types.mac.h b/Engine/source/platform/types.mac.h index e700afac0..fb31d5ea7 100644 --- a/Engine/source/platform/types.mac.h +++ b/Engine/source/platform/types.mac.h @@ -27,10 +27,11 @@ #define FN_CDECL #define STDCALL +#include // size_t is needed to overload new // size_t tends to be OS and compiler specific and may need to // be if/def'ed in the future -typedef unsigned long dsize_t; +typedef size_t dsize_t; /** Platform dependent file date-time structure. The defination of this structure From eab086e1846fb8e52762ef91dcd1b0a4b41dba91 Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Thu, 8 Mar 2018 00:51:52 -0500 Subject: [PATCH 24/26] A buffer overflow in enumerateConsoleClassesByCategory --- Engine/source/console/consoleObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/console/consoleObject.cpp b/Engine/source/console/consoleObject.cpp index 4064d47da..52e2d9256 100644 --- a/Engine/source/console/consoleObject.cpp +++ b/Engine/source/console/consoleObject.cpp @@ -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; } } From 47d5b6ead7b7bb158261203d167ac3f3ea6ec277 Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Thu, 8 Mar 2018 20:59:40 -0500 Subject: [PATCH 25/26] As suggested, extract strlen calls from sizes into variables so it isn't called twice --- Engine/source/T3D/components/component.cpp | 5 +- Engine/source/T3D/fx/particle.cpp | 5 +- Engine/source/T3D/fx/particleEmitter.cpp | 5 +- Engine/source/afx/afxMagicMissile.cpp | 5 +- Engine/source/afx/ce/afxParticleEmitter.cpp | 15 +++-- Engine/source/afx/xm/afxXM_PathConform.cpp | 5 +- Engine/source/app/badWordFilter.cpp | 5 +- Engine/source/app/net/serverQuery.cpp | 55 +++++++++++-------- Engine/source/cinterface/cinterface.cpp | 5 +- Engine/source/console/CMDscan.cpp | 5 +- Engine/source/console/CMDscan.l | 5 +- Engine/source/console/astAlloc.cpp | 5 +- Engine/source/console/console.cpp | 5 +- Engine/source/console/consoleFunctions.cpp | 15 +++-- Engine/source/console/fileSystemFunctions.cpp | 10 ++-- Engine/source/console/simObjectMemento.cpp | 5 +- Engine/source/core/stringTable.cpp | 5 +- Engine/source/core/strings/findMatch.cpp | 5 +- .../source/core/strings/stringFunctions.cpp | 5 +- Engine/source/core/util/zip/centralDir.cpp | 5 +- Engine/source/gfx/gfxStructs.cpp | 5 +- .../source/gui/controls/guiAnimBitmapCtrl.cpp | 5 +- Engine/source/i18n/lang.cpp | 35 +++++++----- .../source/persistence/taml/tamlWriteNode.h | 5 +- .../source/platformWin32/winDInputDevice.cpp | 5 +- Engine/source/platformWin32/winRedbook.cpp | 5 +- .../x86UNIXOGLVideo.client.cpp | 5 +- .../source/platformX86UNIX/x86UNIXRedbook.cpp | 5 +- Engine/source/sim/actionMap.cpp | 5 +- Engine/source/sim/netStringTable.cpp | 10 ++-- Engine/source/sqlite/SQLiteObject.cpp | 10 ++-- Engine/source/util/messaging/eventManager.cpp | 5 +- Engine/source/util/undo.cpp | 10 ++-- 33 files changed, 171 insertions(+), 114 deletions(-) diff --git a/Engine/source/T3D/components/component.cpp b/Engine/source/T3D/components/component.cpp index 1ef7904e9..c7f9dcc2c 100644 --- a/Engine/source/T3D/components/component.cpp +++ b/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, dStrlen(desc) + 1); + dsize_t newDescLen = dStrlen(desc) + 1; + newDesc = new char[newDescLen]; + dStrcpy(newDesc, desc, newDescLen); return newDesc; } diff --git a/Engine/source/T3D/fx/particle.cpp b/Engine/source/T3D/fx/particle.cpp index a528af0d1..66539ab24 100644 --- a/Engine/source/T3D/fx/particle.cpp +++ b/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, dStrlen(animTexFramesString) + 1); + dsize_t tokLen = dStrlen(animTexFramesString) + 1; + char* tokCopy = new char[tokLen]; + dStrcpy(tokCopy, animTexFramesString, tokLen); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) diff --git a/Engine/source/T3D/fx/particleEmitter.cpp b/Engine/source/T3D/fx/particleEmitter.cpp index 00dbadb97..cab153574 100644 --- a/Engine/source/T3D/fx/particleEmitter.cpp +++ b/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 dataBlocks(__FILE__, __LINE__); - char* tokCopy = new char[dStrlen(particleString) + 1]; - dStrcpy(tokCopy, particleString, dStrlen(particleString) + 1); + dsize_t tokLen = dStrlen(particleString) + 1; + char* tokCopy = new char[tokLen]; + dStrcpy(tokCopy, particleString, tokLen); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) diff --git a/Engine/source/afx/afxMagicMissile.cpp b/Engine/source/afx/afxMagicMissile.cpp index 690e3c74b..be42a9941 100644 --- a/Engine/source/afx/afxMagicMissile.cpp +++ b/Engine/source/afx/afxMagicMissile.cpp @@ -446,8 +446,9 @@ bool afxMagicMissileData::onAdd() Vector dataBlocks(__FILE__, __LINE__); // make a copy of points_string - char* tokCopy = new char[dStrlen(wiggle_axis_string) + 1]; - dStrcpy(tokCopy, wiggle_axis_string, dStrlen(wiggle_axis_string) + 1); + 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"); diff --git a/Engine/source/afx/ce/afxParticleEmitter.cpp b/Engine/source/afx/ce/afxParticleEmitter.cpp index 2f7643c8f..1d76b2475 100644 --- a/Engine/source/afx/ce/afxParticleEmitter.cpp +++ b/Engine/source/afx/ce/afxParticleEmitter.cpp @@ -141,8 +141,9 @@ bool afxParticleEmitterData::onAdd() if (tpaths_string != ST_NULLSTRING) { Vector dataBlocks(__FILE__, __LINE__); - char* tokCopy = new char[dStrlen(tpaths_string) + 1]; - dStrcpy(tokCopy, tpaths_string, dStrlen(tpaths_string) + 1); + 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 dataBlocks(__FILE__, __LINE__); - char* tokCopy = new char[dStrlen(epaths_string) + 1]; - dStrcpy(tokCopy, epaths_string, dStrlen(epaths_string) + 1); + 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 dataBlocks(__FILE__, __LINE__); - char* tokCopy = new char[dStrlen(epaths_string) + 1]; - dStrcpy(tokCopy, epaths_string, dStrlen(epaths_string) + 1); + 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) diff --git a/Engine/source/afx/xm/afxXM_PathConform.cpp b/Engine/source/afx/xm/afxXM_PathConform.cpp index 3fde74699..07bd86d92 100644 --- a/Engine/source/afx/xm/afxXM_PathConform.cpp +++ b/Engine/source/afx/xm/afxXM_PathConform.cpp @@ -194,8 +194,9 @@ bool afxXM_PathConformData::onAdd() if (paths_string != ST_NULLSTRING) { Vector dataBlocks(__FILE__, __LINE__); - char* tokCopy = new char[dStrlen(paths_string) + 1]; - dStrcpy(tokCopy, paths_string, dStrlen(paths_string) + 1); + 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) diff --git a/Engine/source/app/badWordFilter.cpp b/Engine/source/app/badWordFilter.cpp index 0a13a9c29..2983a8bb5 100644 --- a/Engine/source/app/badWordFilter.cpp +++ b/Engine/source/app/badWordFilter.cpp @@ -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, dStrlen(baseString) + 1); + dsize_t retLen = dStrlen(baseString) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, baseString, retLen); gBadWordFilter->filterString(ret, replaceStr); return ret; } diff --git a/Engine/source/app/net/serverQuery.cpp b/Engine/source/app/net/serverQuery.cpp index 12a83c454..05d31e531 100644 --- a/Engine/source/app/net/serverQuery.cpp +++ b/Engine/source/app/net/serverQuery.cpp @@ -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, dStrlen(gameType) + 1 ); + 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, dStrlen(missionType) + 1 ); + 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, dStrlen(serverName) + 1 ); + 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,8 +1056,9 @@ 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, strlen(buf) + 1 ); + 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", 5 ); newServer.missionType = (char*) dMalloc( 16 ); @@ -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, dStrlen(guidList) + 1 ); + 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, dStrlen(buf) + 1 ); + 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, dStrlen(stringBuf) + 1 ); + 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, dStrlen(stringBuf) + 1 ); + 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, dStrlen(stringBuf) + 1 ); + 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, dStrlen(stringBuf) + 1 ); + 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, dStrlen(stringBuf) + 1 ); + dsize_t statusLen = dStrlen(stringBuf) + 1; + si->statusString = (char*) dRealloc( (void*) si->statusString, statusLen ); + dStrcpy( si->statusString, stringBuf, statusLen ); } // Update the server browser gui! diff --git a/Engine/source/cinterface/cinterface.cpp b/Engine/source/cinterface/cinterface.cpp index 4f6f1900c..aa0fae035 100644 --- a/Engine/source/cinterface/cinterface.cpp +++ b/Engine/source/cinterface/cinterface.cpp @@ -182,8 +182,9 @@ extern "C" { void torque_setexecutablepath(const char* directory) { - gExecutablePath = new char[dStrlen(directory)+1]; - dStrcpy(gExecutablePath, directory, dStrlen(directory)+1); + 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) diff --git a/Engine/source/console/CMDscan.cpp b/Engine/source/console/CMDscan.cpp index c780fd2a6..c30ac7bc9 100644 --- a/Engine/source/console/CMDscan.cpp +++ b/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, dStrlen(CMDtext)); + dsize_t bufferLen = dStrlen(CMDtext); + char* buffer = (char*)consoleAlloc(bufferLen); + dStrcpy(buffer, CMDtext + 1, bufferLen); CMDlval.str = MakeToken< char* >(buffer, lineIndex); return ret; diff --git a/Engine/source/console/CMDscan.l b/Engine/source/console/CMDscan.l index c4bdc1bf3..e9069fe15 100644 --- a/Engine/source/console/CMDscan.l +++ b/Engine/source/console/CMDscan.l @@ -412,8 +412,9 @@ static int Sc_ScanString(int ret) if(!collapseEscape(CMDtext+1)) return -1; - char* buffer = ( char* ) consoleAlloc( dStrlen( CMDtext ) ); - dStrcpy( buffer, CMDtext + 1, dStrlen( CMDtext ) ); + dsize_t bufferLen = dStrlen( CMDtext ); + char* buffer = ( char* ) consoleAlloc( bufferLen ); + dStrcpy( buffer, CMDtext + 1, bufferLen ); CMDlval.str = MakeToken< char* >( buffer, lineIndex ); return ret; diff --git a/Engine/source/console/astAlloc.cpp b/Engine/source/console/astAlloc.cpp index e897af247..521b6dbcc 100644 --- a/Engine/source/console/astAlloc.cpp +++ b/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, dStrlen(str) + 1); + dStrcpy(ret->str, str, retStrLen); return ret; } diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index be472f197..dc7dde340 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -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(entry.mString), pos, dStrlen(pos) + 1); + dsize_t logStringLen = dStrlen(pos) + 1; + entry.mString = (const char *)consoleLogChunker.alloc(logStringLen); + dStrcpy(const_cast(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 diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index 3ffe200ce..d32b30d31 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -585,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, dStrlen(str) + 1); + dsize_t retLen = dStrlen(str) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, str, retLen); return dStrlwr(ret); } @@ -602,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, dStrlen(str) + 1); + dsize_t retLen = dStrlen(str) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, str, retLen); return dStrupr(ret); } @@ -1826,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, dStrlen(word + 1) + 1 ); + dsize_t retLen = dStrlen(word + 1) + 1; + char* ret = Con::getReturnBuffer(retLen); + dStrcpy( ret, word + 1, retLen ); return ret; } else diff --git a/Engine/source/console/fileSystemFunctions.cpp b/Engine/source/console/fileSystemFunctions.cpp index 0fdafec85..23ef01c24 100644 --- a/Engine/source/console/fileSystemFunctions.cpp +++ b/Engine/source/console/fileSystemFunctions.cpp @@ -617,8 +617,9 @@ DefineEngineFunction(fileBase, String, ( const char* fileName ),, path = szPathCopy; else path++; - char *ret = Con::getReturnBuffer(dStrlen(path) + 1); - dStrcpy(ret, path, dStrlen(path) + 1); + dsize_t retLen = dStrlen(path) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, path, retLen); char *ext = dStrrchr(ret, '.'); if(ext) *ext = 0; @@ -643,8 +644,9 @@ DefineEngineFunction(fileName, String, ( const char* fileName ),, name = szPathCopy; else name++; - char *ret = Con::getReturnBuffer(dStrlen(name) + 1); - dStrcpy(ret, name, dStrlen(name) + 1); + dsize_t retLen = dStrlen(name) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, name, retLen); return ret; } diff --git a/Engine/source/console/simObjectMemento.cpp b/Engine/source/console/simObjectMemento.cpp index 93a9db118..949349442 100644 --- a/Engine/source/console/simObjectMemento.cpp +++ b/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 ], dStrlen(mState) - numCharsToLeftParen + 1 ); + dStrcpy( &tempBuffer[ numCharsToLeftParen + uniqueNameLen ], &mState[ numCharsToLeftParen ], tempBufferLen - numCharsToLeftParen - uniqueNameLen ); } Con::evaluate( tempBuffer ); diff --git a/Engine/source/core/stringTable.cpp b/Engine/source/core/stringTable.cpp index 17f2ca235..d29519198 100644 --- a/Engine/source/core/stringTable.cpp +++ b/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, dStrlen(val) + 1); + (*walk)->val = (char *) mempool.alloc(valLen); + dStrcpy((*walk)->val, val, valLen); ret = (*walk)->val; itemCount ++; } diff --git a/Engine/source/core/strings/findMatch.cpp b/Engine/source/core/strings/findMatch.cpp index bfa7d5a3b..97829a5ca 100644 --- a/Engine/source/core/strings/findMatch.cpp +++ b/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, dStrlen(_expression) + 1); + dsize_t expressionLen = dStrlen(_expression) + 1; + expression = new char[expressionLen]; + dStrcpy(expression, _expression, expressionLen); dStrupr(expression); } diff --git a/Engine/source/core/strings/stringFunctions.cpp b/Engine/source/core/strings/stringFunctions.cpp index 668c9d649..77f7214d0 100644 --- a/Engine/source/core/strings/stringFunctions.cpp +++ b/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, dStrlen(src) + 1); + dsize_t bufferLen = dStrlen(src) + 1; + char *buffer = (char *) dMalloc_r(bufferLen, fileName, lineNumber); + dStrcpy(buffer, src, bufferLen); return buffer; } diff --git a/Engine/source/core/util/zip/centralDir.cpp b/Engine/source/core/util/zip/centralDir.cpp index bf5bef92e..7646bac7a 100644 --- a/Engine/source/core/util/zip/centralDir.cpp +++ b/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, dStrlen(comment)+1); + dsize_t commentLen = dStrlen(comment) + 1; + mFileComment = new char [commentLen]; + dStrcpy(mFileComment, comment, commentLen); } //----------------------------------------------------------------------------- diff --git a/Engine/source/gfx/gfxStructs.cpp b/Engine/source/gfx/gfxStructs.cpp index ff8726b8b..7f64c6ee6 100644 --- a/Engine/source/gfx/gfxStructs.cpp +++ b/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, dStrlen(str) + 1 ); + 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)) \ diff --git a/Engine/source/gui/controls/guiAnimBitmapCtrl.cpp b/Engine/source/gui/controls/guiAnimBitmapCtrl.cpp index 1f29caddc..26ce32376 100644 --- a/Engine/source/gui/controls/guiAnimBitmapCtrl.cpp +++ b/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, dStrlen(data) + 1); + dsize_t tokLen = dStrlen(data) + 1; + char* tokCopy = new char[tokLen]; + dStrcpy(tokCopy, data, tokLen); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) diff --git a/Engine/source/i18n/lang.cpp b/Engine/source/i18n/lang.cpp index 3ed0d344c..7e1efe4a5 100644 --- a/Engine/source/i18n/lang.cpp +++ b/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, dStrlen(langName) + 1); + 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, dStrlen(str) + 1); + 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, dStrlen(str) + 1); + 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, dStrlen(newName) + 1); + 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, dStrlen(langFile) + 1); + 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, dStrlen(str) + 1); + 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, dStrlen(str) + 1); + dsize_t retLen = dStrlen(str) + 1; + char * ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, str, retLen); return ret; } diff --git a/Engine/source/persistence/taml/tamlWriteNode.h b/Engine/source/persistence/taml/tamlWriteNode.h index 015224589..b406a54d8 100644 --- a/Engine/source/persistence/taml/tamlWriteNode.h +++ b/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, dStrlen(pValue) + 1 ); + dsize_t valueLen = dStrlen(pValue) + 1; + mpValue = new char[ valueLen ]; + dStrcpy( (char *)mpValue, pValue, valueLen ); } diff --git a/Engine/source/platformWin32/winDInputDevice.cpp b/Engine/source/platformWin32/winDInputDevice.cpp index c2969c65c..9ce308090 100644 --- a/Engine/source/platformWin32/winDInputDevice.cpp +++ b/Engine/source/platformWin32/winDInputDevice.cpp @@ -1575,8 +1575,9 @@ const char* DInputDevice::getJoystickAxesString() } } - char* returnString = Con::getReturnBuffer( dStrlen( buf ) + 1 ); - dStrcpy( returnString, buf, dStrlen(buf) + 1 ); + dsize_t returnLen = dStrlen(buf) + 1; + char* returnString = Con::getReturnBuffer(returnLen); + dStrcpy( returnString, buf, returnLen ); return( returnString ); } diff --git a/Engine/source/platformWin32/winRedbook.cpp b/Engine/source/platformWin32/winRedbook.cpp index 40b030c64..beef38dd0 100644 --- a/Engine/source/platformWin32/winRedbook.cpp +++ b/Engine/source/platformWin32/winRedbook.cpp @@ -83,8 +83,9 @@ void installRedBookDevices() if(::GetDriveTypeA(str) == DRIVE_CDROM) { Win32RedBookDevice * device = new Win32RedBookDevice; - device->mDeviceName = new char[dStrlen(str) + 1]; - dStrcpy(device->mDeviceName, str, dStrlen(str) + 1); + dsize_t deviceNameLen = dStrlen(str) + 1; + device->mDeviceName = new char[deviceNameLen]; + dStrcpy(device->mDeviceName, str, deviceNameLen); RedBook::installDevice(device); } diff --git a/Engine/source/platformX86UNIX/x86UNIXOGLVideo.client.cpp b/Engine/source/platformX86UNIX/x86UNIXOGLVideo.client.cpp index 384aade9e..9db3236c5 100644 --- a/Engine/source/platformX86UNIX/x86UNIXOGLVideo.client.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXOGLVideo.client.cpp @@ -40,8 +40,9 @@ bool InitOpenGL() // Get the video settings from the prefs: const char* resString = Con::getVariable( "$pref::Video::resolution" ); - char* tempBuf = new char[dStrlen( resString ) + 1]; - dStrcpy( tempBuf, resString, dStrlen(resString) + 1 ); + dsize_t tempBufLen = dStrlen(resString) + 1; + char* tempBuf = new char[tempBufLen]; + dStrcpy( tempBuf, resString, tempBufLen ); char* temp = dStrtok( tempBuf, " x\0" ); U32 width = ( temp ? dAtoi( temp ) : 800 ); temp = dStrtok( NULL, " x\0" ); diff --git a/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp b/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp index 3484a56ce..d24902230 100644 --- a/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp @@ -101,8 +101,9 @@ void UnixRedBookDevice::setDeviceInfo(S32 deviceId, const char *deviceName) { #if !defined(__FreeBSD__) mDeviceId = deviceId; - mDeviceName = new char[dStrlen(deviceName) + 1]; - dStrcpy(mDeviceName, deviceName, dStrlen(deviceName) + 1); + dsize_t deviceNameLen = dStrlen(deviceName) + 1; + mDeviceName = new char[deviceNameLen]; + dStrcpy(mDeviceName, deviceName, deviceNameLen); #endif // !defined(__FreeBSD__) } diff --git a/Engine/source/sim/actionMap.cpp b/Engine/source/sim/actionMap.cpp index 1d0fbe8b5..ca2932e84 100644 --- a/Engine/source/sim/actionMap.cpp +++ b/Engine/source/sim/actionMap.cpp @@ -908,8 +908,9 @@ const char* ActionMap::getDeadZone( const char* device, const char* action ) { char buf[64]; dSprintf( buf, sizeof( buf ), "%g %g", mapNode->deadZoneBegin, mapNode->deadZoneEnd ); - char* returnString = Con::getReturnBuffer( dStrlen( buf ) + 1 ); - dStrcpy( returnString, buf, dStrlen(buf) + 1 ); + dsize_t returnLen = dStrlen(buf) + 1; + char* returnString = Con::getReturnBuffer( returnLen ); + dStrcpy( returnString, buf, returnLen ); return( returnString ); } else diff --git a/Engine/source/sim/netStringTable.cpp b/Engine/source/sim/netStringTable.cpp index c21377885..83a059eff 100644 --- a/Engine/source/sim/netStringTable.cpp +++ b/Engine/source/sim/netStringTable.cpp @@ -96,8 +96,9 @@ U32 NetStringTable::addString(const char *string) size = newSize; } table[e].refCount++; - table[e].string = (char *) allocator->alloc(dStrlen(string) + 1); - dStrcpy(table[e].string, string, dStrlen(string) + 1); + dsize_t stringLen = dStrlen(string) + 1; + table[e].string = (char *) allocator->alloc(stringLen); + dStrcpy(table[e].string, string, stringLen); table[e].next = hashTable[bucket]; hashTable[bucket] = e; table[e].link = firstValid; @@ -178,8 +179,9 @@ void NetStringTable::repack() const char *prevStr = table[walk].string; - table[walk].string = (char *) newAllocator->alloc(dStrlen(prevStr) + 1); - dStrcpy(table[walk].string, prevStr, dStrlen(prevStr) + 1); + dsize_t prevStrLen = dStrlen(prevStr) + 1; + table[walk].string = (char *) newAllocator->alloc(prevStrLen); + dStrcpy(table[walk].string, prevStr, prevStrLen); } delete allocator; allocator = newAllocator; diff --git a/Engine/source/sqlite/SQLiteObject.cpp b/Engine/source/sqlite/SQLiteObject.cpp index a2900ab30..4cba76720 100644 --- a/Engine/source/sqlite/SQLiteObject.cpp +++ b/Engine/source/sqlite/SQLiteObject.cpp @@ -157,13 +157,15 @@ S32 Callback(void *pArg, S32 argc, char **argv, char **columnNames) { // DBEUG CODE // Con::printf("%s = %s\n", columnNames[i], argv[i] ? argv[i] : "NULL"); - name = new char[dStrlen(columnNames[i]) + 1]; - dStrcpy(name, columnNames[i], dStrlen(columnNames[i]) + 1); + dsize_t columnNameLen = dStrlen(columnNames[i]) + 1; + name = new char[columnNameLen]; + dStrcpy(name, columnNames[i], columnNameLen); pRow->vColumnNames.push_back(name); if (argv[i]) { - value = new char[dStrlen(argv[i]) + 1]; - dStrcpy(value, argv[i], dStrlen(argv[i]) + 1); + dsize_t valueLen = dStrlen(argv[i]) + 1; + value = new char[valueLen]; + dStrcpy(value, argv[i], valueLen); pRow->vColumnValues.push_back(value); } else diff --git a/Engine/source/util/messaging/eventManager.cpp b/Engine/source/util/messaging/eventManager.cpp index 5463e1efc..0edfa98fc 100644 --- a/Engine/source/util/messaging/eventManager.cpp +++ b/Engine/source/util/messaging/eventManager.cpp @@ -288,8 +288,9 @@ bool EventManager::subscribe(SimObject *callbackObj, const char* event, const ch } else { - cb = new char[dStrlen(callback) + 1]; - dStrcpy(cb, callback, dStrlen(callback) + 1); + dsize_t cbLen = dStrlen(callback) + 1; + cb = new char[cbLen]; + dStrcpy(cb, callback, cbLen); } // Create the subscriber object. diff --git a/Engine/source/util/undo.cpp b/Engine/source/util/undo.cpp index 11334a793..7ea0acc8c 100644 --- a/Engine/source/util/undo.cpp +++ b/Engine/source/util/undo.cpp @@ -545,8 +545,9 @@ DefineConsoleMethod(UndoManager, getNextUndoName, const char *, (),, "UndoManage const char *name = object->getNextUndoName(); if(!name) return NULL; - char *ret = Con::getReturnBuffer(dStrlen(name) + 1); - dStrcpy(ret, name, dStrlen(name) + 1); + dsize_t retLen = dStrlen(name) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, name, retLen); return ret; } @@ -556,8 +557,9 @@ DefineConsoleMethod(UndoManager, getNextRedoName, const char *, (),, "UndoManage const char *name = object->getNextRedoName(); if(!name) return NULL; - char *ret = Con::getReturnBuffer(dStrlen(name) + 1); - dStrcpy(ret, name, dStrlen(name) + 1); + dsize_t retLen = dStrlen(name) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, name, retLen); return ret; } From 8f947d52519b49242f63c2197631c4a8c84dfdb4 Mon Sep 17 00:00:00 2001 From: Areloch Date: Sat, 17 Mar 2018 14:37:07 -0500 Subject: [PATCH 26/26] Adds a convenience function to refresh the console dialog. --- Engine/source/gui/controls/guiConsole.cpp | 6 ++++++ Engine/source/gui/controls/guiConsole.h | 4 ++++ Templates/BaseGame/game/core/console/main.cs | 2 ++ Templates/Full/game/core/art/gui/console.gui | 2 ++ 4 files changed, 14 insertions(+) diff --git a/Engine/source/gui/controls/guiConsole.cpp b/Engine/source/gui/controls/guiConsole.cpp index b8987e8df..d063272bf 100644 --- a/Engine/source/gui/controls/guiConsole.cpp +++ b/Engine/source/gui/controls/guiConsole.cpp @@ -284,4 +284,10 @@ DefineEngineMethod(GuiConsole, toggleNormalFilter, void, (), , "Toggles the normal messages filter.") { object->toggleNormalFilter(); +} + +DefineEngineMethod(GuiConsole, refresh, void, (), , + "Refreshes the displayed messages.") +{ + object->refresh(); } \ No newline at end of file diff --git a/Engine/source/gui/controls/guiConsole.h b/Engine/source/gui/controls/guiConsole.h index 8b9450e09..2ef9eb7c8 100644 --- a/Engine/source/gui/controls/guiConsole.h +++ b/Engine/source/gui/controls/guiConsole.h @@ -89,6 +89,10 @@ class GuiConsole : public GuiArrayCtrl { setDisplayFilters(mDisplayErrors, mDisplayWarnings, !mDisplayNormalMessages); } + void refresh() + { + setDisplayFilters(mDisplayErrors, mDisplayWarnings, mDisplayNormalMessages); + } void refreshLogText(); }; diff --git a/Templates/BaseGame/game/core/console/main.cs b/Templates/BaseGame/game/core/console/main.cs index 47894f7e4..3d89234b8 100644 --- a/Templates/BaseGame/game/core/console/main.cs +++ b/Templates/BaseGame/game/core/console/main.cs @@ -104,6 +104,8 @@ function ConsoleDlg::onWake(%this) ConsoleDlgErrorFilterBtn.setStateOn(ConsoleMessageLogView.getErrorFilter()); ConsoleDlgWarnFilterBtn.setStateOn(ConsoleMessageLogView.getWarnFilter()); ConsoleDlgNormalFilterBtn.setStateOn(ConsoleMessageLogView.getNormalFilter()); + + ConsoleMessageLogView.refresh(); } function ConsoleDlg::setAlpha( %this, %alpha) diff --git a/Templates/Full/game/core/art/gui/console.gui b/Templates/Full/game/core/art/gui/console.gui index 16300e4ac..fd3a2c0e5 100644 --- a/Templates/Full/game/core/art/gui/console.gui +++ b/Templates/Full/game/core/art/gui/console.gui @@ -317,6 +317,8 @@ function ConsoleDlg::onWake(%this) ConsoleDlgErrorFilterBtn.setStateOn(ConsoleMessageLogView.getErrorFilter()); ConsoleDlgWarnFilterBtn.setStateOn(ConsoleMessageLogView.getWarnFilter()); ConsoleDlgNormalFilterBtn.setStateOn(ConsoleMessageLogView.getNormalFilter()); + + ConsoleMessageLogView.refresh(); } function ConsoleDlgErrorFilterBtn::onClick(%this)