diff --git a/core/vm/sp_vm_function.cpp b/core/vm/sp_vm_function.cpp index 30615034..4a008120 100644 --- a/core/vm/sp_vm_function.cpp +++ b/core/vm/sp_vm_function.cpp @@ -200,10 +200,12 @@ void CFunction::Cancel() int CFunction::Execute(cell_t *result) { int err = SP_ERROR_NONE; + if (!IsRunnable()) { m_errorstate = SP_ERROR_NOT_RUNNABLE; } + if (m_errorstate != SP_ERROR_NONE) { err = m_errorstate; @@ -245,7 +247,9 @@ int CFunction::Execute(cell_t *result) { memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size); } - } else { + } + else + { /* Calculate cells required for the string */ size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t); @@ -260,6 +264,7 @@ int CFunction::Execute(cell_t *result) /* Copy original string if necessary */ if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL)) { + /* Cut off UTF-8 properly */ if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8) { if ((err=m_pContext->StringToLocalUTF8(temp_info[i].local_addr, @@ -270,7 +275,15 @@ int CFunction::Execute(cell_t *result) { break; } - } else { + } + /* Copy a binary blob */ + else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY) + { + memmove(temp_info[i].phys_addr, temp_info[i].orig_addr, temp_info[i].size); + } + /* Copy ASCII characters */ + else + { if ((err=m_pContext->StringToLocal(temp_info[i].local_addr, temp_info[i].size, (const char *)temp_info[i].orig_addr)) @@ -283,7 +296,9 @@ int CFunction::Execute(cell_t *result) } /* End array/string calculation */ /* Update the pushed parameter with the byref local address */ temp_params[i] = temp_info[i].local_addr; - } else { + } + else + { /* Just copy the value normally */ temp_params[i] = m_params[i]; } @@ -296,7 +311,9 @@ int CFunction::Execute(cell_t *result) { docopies = false; } - } else { + } + else + { docopies = false; } @@ -307,6 +324,7 @@ int CFunction::Execute(cell_t *result) { continue; } + if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK)) { if (temp_info[i].orig_addr) @@ -314,11 +332,16 @@ int CFunction::Execute(cell_t *result) if (temp_info[i].str.is_sz) { memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size); - } else { + + } + else + { if (temp_info[i].size == 1) { *temp_info[i].orig_addr = *(temp_info[i].phys_addr); - } else { + } + else + { memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size * sizeof(cell_t)); @@ -326,6 +349,7 @@ int CFunction::Execute(cell_t *result) } } } + if ((err=m_pContext->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE) { return err; diff --git a/plugins/include/functions.inc b/plugins/include/functions.inc index bef2f22c..8cd69bf4 100644 --- a/plugins/include/functions.inc +++ b/plugins/include/functions.inc @@ -61,9 +61,12 @@ enum ExecType /** * @section Flags that are used with Call_PushArrayEx() and Call_PushStringEx() */ + #define SM_PARAM_COPYBACK (1<<0) /**< Copy an array/reference back after call */ + #define SM_PARAM_STRING_UTF8 (1<<0) /**< String should be UTF-8 handled */ #define SM_PARAM_STRING_COPY (1<<1) /**< String should be copied into the plugin */ +#define SM_PARAM_STRING_BINARY (1<<2) /**< Treat the string as a binary string */ /** * @endsection @@ -311,6 +314,7 @@ native Call_PushString(const String:value[]); * @param length Length of string buffer. * @param szflags Flags determining how string should be handled. * See SP_PARAM_STRING_* constants for details. + * The default (0) is to push ASCII. * @param cpflags Whether or not changes should be copied back to the input array. * See SP_PARAM_* constants for details. * @noreturn diff --git a/public/ISourceMod.h b/public/ISourceMod.h index 66b21090..06f1650b 100644 --- a/public/ISourceMod.h +++ b/public/ISourceMod.h @@ -43,7 +43,7 @@ #include #define SMINTERFACE_SOURCEMOD_NAME "ISourceMod" -#define SMINTERFACE_SOURCEMOD_VERSION 6 +#define SMINTERFACE_SOURCEMOD_VERSION 7 /** * @brief Forward declaration of the KeyValues class. diff --git a/public/sourcepawn/sp_vm_api.h b/public/sourcepawn/sp_vm_api.h index b0f4b917..100dcaaa 100644 --- a/public/sourcepawn/sp_vm_api.h +++ b/public/sourcepawn/sp_vm_api.h @@ -61,9 +61,13 @@ namespace SourcePawn { class IVirtualMachine; + /* Parameter flags */ #define SM_PARAM_COPYBACK (1<<0) /**< Copy an array/reference back after call */ + + /* String parameter flags (separate from parameter flags) */ #define SM_PARAM_STRING_UTF8 (1<<0) /**< String should be UTF-8 handled */ #define SM_PARAM_STRING_COPY (1<<1) /**< String should be copied into the plugin */ + #define SM_PARAM_STRING_BINARY (1<<2) /**< String should be handled as binary data */ #if defined SOURCEMOD_BUILD /** @@ -151,11 +155,13 @@ namespace SourcePawn /** * @brief Pushes a string or string buffer. + * * NOTE: On Execute, the pointer passed will be modified if copy-back is enabled. * * @param buffer Pointer to string buffer. * @param length Length of buffer. - * @param sz_flags String flags. + * @param sz_flags String flags. In copy mode, the string will be copied + * according to the handling (ascii, utf-8, binary, etc). * @param cp_flags Copy-back flags. * @return Error code, if any. */