diff --git a/client/SDL/SDL2/sdl_kbd.cpp b/client/SDL/SDL2/sdl_kbd.cpp index 28578eeac..67db18a4a 100644 --- a/client/SDL/SDL2/sdl_kbd.cpp +++ b/client/SDL/SDL2/sdl_kbd.cpp @@ -25,6 +25,7 @@ #include +#include #include #include @@ -507,14 +508,7 @@ std::list sdlInput::tokenize(const std::string& data, const std::st bool sdlInput::extract(const std::string& token, uint32_t& key, uint32_t& value) { - int rc = sscanf(token.c_str(), "%" PRIu32 "=%" PRIu32, &key, &value); - if (rc != 2) - rc = sscanf(token.c_str(), "%" PRIx32 "=%" PRIx32 "", &key, &value); - if (rc != 2) - rc = sscanf(token.c_str(), "%" PRIu32 "=%" PRIx32, &key, &value); - if (rc != 2) - rc = sscanf(token.c_str(), "%" PRIx32 "=%" PRIu32, &key, &value); - return (rc == 2); + return freerdp_extract_key_value(token.c_str(), &key, &value); } uint32_t sdlInput::remapScancode(uint32_t scancode) diff --git a/client/SDL/SDL3/sdl_kbd.cpp b/client/SDL/SDL3/sdl_kbd.cpp index c2f7c52f7..f6b3c6683 100644 --- a/client/SDL/SDL3/sdl_kbd.cpp +++ b/client/SDL/SDL3/sdl_kbd.cpp @@ -27,6 +27,7 @@ #include +#include #include #include @@ -483,14 +484,7 @@ std::list sdlInput::tokenize(const std::string& data, const std::st bool sdlInput::extract(const std::string& token, uint32_t& key, uint32_t& value) { - int rc = sscanf(token.c_str(), "%" PRIu32 "=%" PRIu32, &key, &value); - if (rc != 2) - rc = sscanf(token.c_str(), "%" PRIx32 "=%" PRIx32 "", &key, &value); - if (rc != 2) - rc = sscanf(token.c_str(), "%" PRIu32 "=%" PRIx32, &key, &value); - if (rc != 2) - rc = sscanf(token.c_str(), "%" PRIx32 "=%" PRIu32, &key, &value); - return (rc == 2); + return freerdp_extract_key_value(token.c_str(), &key, &value); } uint32_t sdlInput::remapScancode(uint32_t scancode) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 85c3dc773..83b97175d 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -2442,14 +2443,7 @@ static BOOL check_kbd_remap_valid(const char* token) if (strlen(token) > 10) return FALSE; - int rc = sscanf(token, "%" PRIu32 "=%" PRIu32, &key, &value); - if (rc != 2) - rc = sscanf(token, "%" PRIx32 "=%" PRIx32 "", &key, &value); - if (rc != 2) - rc = sscanf(token, "%" PRIu32 "=%" PRIx32, &key, &value); - if (rc != 2) - rc = sscanf(token, "%" PRIx32 "=%" PRIu32, &key, &value); - if (rc != 2) + if (!freerdp_extract_key_value(token, &key, &value)) { WLog_WARN(TAG, "/kbd:remap invalid entry '%s'", token); return FALSE; diff --git a/include/freerdp/utils/string.h b/include/freerdp/utils/string.h index 1268360a0..41f28ec05 100644 --- a/include/freerdp/utils/string.h +++ b/include/freerdp/utils/string.h @@ -35,6 +35,18 @@ extern "C" FREERDP_API const char* rdp_cluster_info_flags_to_string(UINT32 flags, char* buffer, size_t size); + /** @brief extracts = pairs from a string + * + * @param str The string to extract data from, must not be \b NULL + * @param pkey A pointer to store the key value, must not be \b NULL + * @param pvalue A pointer to store the value, must not be \b NULL + * + * @return \b TRUE if successfully extracted, \b FALSE if no matching data was found + * + * @since version 3.9.0 + */ + FREERDP_API BOOL freerdp_extract_key_value(const char* str, UINT32* pkey, UINT32* pvalue); + #ifdef __cplusplus } #endif diff --git a/libfreerdp/core/proxy.c b/libfreerdp/core/proxy.c index d96127eff..4a3a384e4 100644 --- a/libfreerdp/core/proxy.c +++ b/libfreerdp/core/proxy.c @@ -247,10 +247,9 @@ static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy) if (rangedelim != NULL) { const char* range = rangedelim + 1; - unsigned sub = 0; - int rc = sscanf(range, "%u", &sub); + const unsigned long sub = strtoul(range, NULL, 0); - if ((rc == 1) && (rc >= 0) && (sub <= UINT8_MAX)) + if ((errno == 0) && (sub <= UINT8_MAX)) { *rangedelim = '\0'; diff --git a/libfreerdp/locale/keyboard.c b/libfreerdp/locale/keyboard.c index 56b6f477f..d8f00e0b1 100644 --- a/libfreerdp/locale/keyboard.c +++ b/libfreerdp/locale/keyboard.c @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -351,14 +352,7 @@ DWORD freerdp_keyboard_init_ex(DWORD keyboardLayoutId, const char* keyboardRemap { DWORD key = 0; DWORD value = 0; - int rc = sscanf(token, "%" PRIu32 "=%" PRIu32, &key, &value); - if (rc != 2) - rc = sscanf(token, "%" PRIx32 "=%" PRIx32 "", &key, &value); - if (rc != 2) - rc = sscanf(token, "%" PRIu32 "=%" PRIx32, &key, &value); - if (rc != 2) - rc = sscanf(token, "%" PRIx32 "=%" PRIu32, &key, &value); - if (rc != 2) + if (!freerdp_extract_key_value(token, &key, &value)) goto fail; if (key >= ARRAYSIZE(REMAPPING_TABLE)) goto fail; diff --git a/libfreerdp/utils/string.c b/libfreerdp/utils/string.c index 2b5826f0b..8da8f6d36 100644 --- a/libfreerdp/utils/string.c +++ b/libfreerdp/utils/string.c @@ -19,6 +19,8 @@ * limitations under the License. */ +#include + #include #include @@ -103,3 +105,22 @@ const char* rdp_cluster_info_flags_to_string(UINT32 flags, char* buffer, size_t } return buffer; } + +BOOL freerdp_extract_key_value(const char* str, UINT32* pkey, UINT32* pvalue) +{ + if (!str || !pkey || !pvalue) + return FALSE; + + char* end1 = NULL; + unsigned long key = strtoul(str, &end1, 0); + if ((errno != 0) || !end1 || (*end1 != '=') || (key > UINT32_MAX)) + return FALSE; + + unsigned long val = strtoul(&end1[1], NULL, 0); + if ((errno != 0) || (val > UINT32_MAX)) + return FALSE; + + *pkey = (UINT32)key; + *pvalue = (UINT32)val; + return TRUE; +}