From 732a05dde0bbcce5446e0cc0b8297a2c6eba33f1 Mon Sep 17 00:00:00 2001 From: IgnacioFDM Date: Wed, 31 Aug 2016 15:34:02 -0300 Subject: [PATCH] Back out changes in #366 and introduce read_argv_int/float() * Revert "Extend "read_argv" native" This reverts commit aaa2934595379c371513cb9dd23de8f3c5e16d93. This broke binary compatibility with either older, already compiled plugins, or newly compiled plugins if you forgot to update .inc headers. This happened because read_argv used to receive maxlen by value, and after this commit it receives it by reference. This causes read_argv either to fail, or worse, to buffer overflow, resulting in a security vulnerability. Newly introduced functionality for read_argv should be added with a new, separate native. * Add "read_argv_int" & "read_argv_float" natives --- amxmodx/amxmodx.cpp | 39 ++++++++++++++++++++++-------- plugins/include/amxmodx.inc | 47 +++++++++++++++++++++---------------- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/amxmodx/amxmodx.cpp b/amxmodx/amxmodx.cpp index e89ec579..f8075b71 100755 --- a/amxmodx/amxmodx.cpp +++ b/amxmodx/amxmodx.cpp @@ -2460,19 +2460,36 @@ static cell AMX_NATIVE_CALL read_argv(AMX *amx, cell *params) /* 3 param */ int argc = params[1]; const char *value = g_fakecmd.notify ? (argc >= 0 && argc < 3 ? g_fakecmd.argv[argc] : "") : CMD_ARGV(argc); + return set_amxstring_utf8(amx, params[2], value, strlen(value), params[3]); +} - switch (*params / sizeof(cell)) +static cell AMX_NATIVE_CALL read_argv_int(AMX *amx, cell *params) /* 1 param */ +{ + int argc = params[1]; + + if (argc <= 0) { - case 1: - return atoi(value); - case 3: - return set_amxstring_utf8(amx, params[2], value, strlen(value), *get_amxaddr(amx, params[3])); - default: - cell *fCell = get_amxaddr(amx, params[2]); - REAL fparam = static_cast(atof(value)); - *fCell = amx_ftoc(fparam); - return static_cast(fparam); + return 0; } + + const char *value = g_fakecmd.notify ? (argc >= 1 && argc < 3 ? g_fakecmd.argv[argc] : "") : CMD_ARGV(argc); + + return atoi(value); +} + +static cell AMX_NATIVE_CALL read_argv_float(AMX *amx, cell *params) /* 1 param */ +{ + int argc = params[1]; + + if (argc <= 0) + { + return 0; + } + + const char *value = g_fakecmd.notify ? (argc >= 1 && argc < 3 ? g_fakecmd.argv[argc] : "") : CMD_ARGV(argc); + float flValue = atof(value); + + return amx_ftoc(flValue); } static cell AMX_NATIVE_CALL read_args(AMX *amx, cell *params) /* 2 param */ @@ -4754,6 +4771,8 @@ AMX_NATIVE_INFO amxmodx_Natives[] = {"read_argc", read_argc}, {"read_args", read_args}, {"read_argv", read_argv}, + {"read_argv_int", read_argv_int}, + {"read_argv_float", read_argv_float}, {"read_data", read_data}, {"read_datanum", read_datanum}, {"read_datatype", read_datatype}, diff --git a/plugins/include/amxmodx.inc b/plugins/include/amxmodx.inc index 9f6f8050..888802cf 100755 --- a/plugins/include/amxmodx.inc +++ b/plugins/include/amxmodx.inc @@ -1318,32 +1318,39 @@ native get_playersnum(flag = 0); native get_players(players[MAX_PLAYERS], &num, const flags[] = "", const team[] = ""); /** - * Retrieves argument of client command. + * Retrieves argument of client command as string. * * @note Should only be used inside of the client_command() forward. - * @note Usage examples: - * value = read_argv(1); - * read_argv(2, floatvalue); - * written = read_argv(3, buffer, buffersize); * * @param id Argument index starting from 1, 0 returns the command itself - * @param ... Changes the native's behavior depending on how many - * additional parameters are provided: - * 0 - Return the argument integer value directly - * 1 - Store the argument float value in the variable passed - * as the second parameter - * 2 - Copy the argument string value to the buffer provided - * in the second parameter, using the third as the - * maximum buffer size + * @param output Buffer to copy command argument to + * @param len Maximum buffer size * - * @return Changes depending on how many additional parameters are - * provided: - * 0 - Returns the argument integer value - * 1 - Returns the argument float value, converted - * (truncated) to an integer - * 2 - Returns the number of cells written to the buffer + * @return Number of cells written to buffer */ -native read_argv(id, any:...); +native read_argv(id, output[], len); + +/** + * Retrieves argument of client command as integer value. + * + * @note Should only be used inside of the client_command() forward. + * + * @param id Argument index starting from 1 + * + * @return Integer value + */ +native read_argv_int(id); + +/** + * Retrieves argument of client command as float value. + * + * @note Should only be used inside of the client_command() forward. + * + * @param id Argument index starting from 1 + * + * @return Float value + */ +native Float:read_argv_float(id); /** * Retrieves full client command string.