diff --git a/cleo_plugins/DebugUtils/DebugUtils.cpp b/cleo_plugins/DebugUtils/DebugUtils.cpp index f96e700b..bd999f82 100644 --- a/cleo_plugins/DebugUtils/DebugUtils.cpp +++ b/cleo_plugins/DebugUtils/DebugUtils.cpp @@ -232,8 +232,8 @@ class DebugUtils } else // breakpoint formatted name string { - auto format = CLEO_ReadStringOpcodeParam(thread); - name = CLEO_ReadParamsFormatted(thread, format); + OPCODE_READ_PARAM_STRING_FORMATTED(nameStr); + name = nameStr; } pausedScripts.emplace_back(thread, name.c_str()); @@ -262,8 +262,7 @@ class DebugUtils return OR_CONTINUE; } - auto format = CLEO_ReadStringOpcodeParam(thread); - auto message = CLEO_ReadParamsFormatted(thread, format); + OPCODE_READ_PARAM_STRING_FORMATTED(message); CLEO_Log(eLogLevel::Debug, message); return OR_CONTINUE; diff --git a/cleo_plugins/FileSystemOperations/FileSystemOperations.cpp b/cleo_plugins/FileSystemOperations/FileSystemOperations.cpp index 6b09d0b1..140aabfc 100644 --- a/cleo_plugins/FileSystemOperations/FileSystemOperations.cpp +++ b/cleo_plugins/FileSystemOperations/FileSystemOperations.cpp @@ -355,8 +355,7 @@ class FileSystemOperations static OpcodeResult WINAPI opcode_0AD9(CRunningScript* thread) { OPCODE_READ_PARAM_FILE_HANDLE(handle); - OPCODE_READ_PARAM_STRING(format); - static char text[4 * MAX_STR_LEN]; CLEO_ReadParamsFormatted(thread, format, text, MAX_STR_LEN); + OPCODE_READ_PARAM_STRING_FORMATTED(text); auto ok = File::writeString(handle, text); if (!ok) diff --git a/cleo_sdk/CLEO_Utils.h b/cleo_sdk/CLEO_Utils.h index 3555d8e6..93f42f24 100644 --- a/cleo_sdk/CLEO_Utils.h +++ b/cleo_sdk/CLEO_Utils.h @@ -691,9 +691,11 @@ namespace CLEO #define OPCODE_READ_PARAM_STRING_LEN(_varName, _maxLen) char _buff_##_varName[_maxLen + 1]; const char* ##_varName = _readParamText(thread, _buff_##_varName, _maxLen + 1); if(##_varName != nullptr) ##_varName = _buff_##_varName; if(!_paramWasString()) { return OpcodeResult::OR_INTERRUPT; } #define OPCODE_READ_PARAM_STRING_FORMATTED(_varName) char _buff_format_##_varName[MAX_STR_LEN + 1]; const char* _format_##_varName = _readParamText(thread, _buff_format_##_varName, MAX_STR_LEN + 1); if(!_paramWasString()) { return OpcodeResult::OR_INTERRUPT; } \ - char _varName[2 * MAX_STR_LEN + 1]; char* _varName##Ok = CLEO_ReadParamsFormatted(thread, _buff_format_##_varName, _varName, sizeof(_varName)); + char _varName[2 * MAX_STR_LEN + 1]; char* _varName##Ok = CLEO_ReadParamsFormatted(thread, _buff_format_##_varName, _varName, sizeof(_varName)); \ + if(_varName##Ok == nullptr) { SHOW_ERROR("Invalid formatted string in script %s \nScript suspended.", CLEO::ScriptInfoStr(thread).c_str()); return thread->Suspend(); } - #define OPCODE_READ_PARAMS_FORMATTED(_format, _varName) char _varName[2 * MAX_STR_LEN + 1]; char* _varName##Ok = CLEO_ReadParamsFormatted(thread, _format, _varName, sizeof(_varName)); + #define OPCODE_READ_PARAMS_FORMATTED(_format, _varName) char _varName[2 * MAX_STR_LEN + 1]; char* _varName##Ok = CLEO_ReadParamsFormatted(thread, _format, _varName, sizeof(_varName)); \ + if(_varName##Ok == nullptr) { SHOW_ERROR("Invalid formatted string in script %s \nScript suspended.", CLEO::ScriptInfoStr(thread).c_str()); return thread->Suspend(); } #define OPCODE_READ_PARAM_FILEPATH(_varName) char _buff_##_varName[512]; const char* ##_varName = _readParamText(thread, _buff_##_varName, 512); if(##_varName != nullptr) ##_varName = _buff_##_varName; if(_paramWasString()) CLEO_ResolvePath(thread, _buff_##_varName, 512); else return OpcodeResult::OR_INTERRUPT; \ if(!FilepathIsSafe(thread, ##_varName)) { SHOW_ERROR("Forbidden file path '%s' outside game directories in script %s \nScript suspended.", ##_varName, ScriptInfoStr(thread).c_str()); return thread->Suspend(); } diff --git a/source/CCustomOpcodeSystem.cpp b/source/CCustomOpcodeSystem.cpp index 58ecbe4e..a55e34a6 100644 --- a/source/CCustomOpcodeSystem.cpp +++ b/source/CCustomOpcodeSystem.cpp @@ -481,7 +481,7 @@ namespace CLEO // invalid input arguments if(outputStr == nullptr || len == 0) { - LOG_WARNING(thread, "ReadFormattedString invalid input arg(s)"); + LOG_WARNING(thread, "ReadFormattedString invalid input arg(s) in script %s", ((CCustomScript*)thread)->GetInfoStr().c_str()); SkipUnusedVarArgs(thread); return -1; // error } @@ -498,10 +498,19 @@ namespace CLEO if (*iter == '%') { + // end of format string + if (iter[1] == '\0') + { + LOG_WARNING(thread, "ReadFormattedString encountered incomplete format specifier in script %s", ((CCustomScript*)thread)->GetInfoStr().c_str()); + SkipUnusedVarArgs(thread); + return -1; // error + } + + // escaped % character if (iter[1] == '%') { if (written++ >= len) goto _ReadFormattedString_OutOfMemory; - *outIter++ = '%'; /* "%%"->'%' */ + *outIter++ = '%'; iter += 2; continue; }