From e6e87eb3b3875e3f62a68f83cf7d26b7628f2ca6 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 22 Nov 2018 16:28:30 +0100 Subject: [PATCH] Unified strto[u]l in cmdline.c To clean up code all integer conversions are now done by a helper function with proper checks in place. --- client/common/cmdline.c | 340 ++++++++++++++++++++++++++---------------------- 1 file changed, 183 insertions(+), 157 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index d175e83..947f750 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -58,6 +58,46 @@ static BOOL copy_value(const char* value, char** dst) return (*dst) != NULL; } +static BOOL value_to_int(const char* value, LONGLONG* result, LONGLONG min, LONGLONG max) +{ + long long rc; + + if (!value || !result) + return FALSE; + + errno = 0; + rc = _strtoi64(value, NULL, 0); + + if (errno != 0) + return FALSE; + + if ((rc < min) || (rc > max)) + return FALSE; + + *result = rc; + return TRUE; +} + +static BOOL value_to_uint(const char* value, ULONGLONG* result, ULONGLONG min, ULONGLONG max) +{ + unsigned long long rc; + + if (!value || !result) + return FALSE; + + errno = 0; + rc = _strtoui64(value, NULL, 0); + + if (errno != 0) + return FALSE; + + if ((rc < min) || (rc > max)) + return FALSE; + + *result = rc; + return TRUE; +} + BOOL freerdp_client_print_version(void) { printf("This is FreeRDP version %s (%s)\n", FREERDP_VERSION_FULL, @@ -955,12 +995,10 @@ BOOL freerdp_parse_hostname(const char* hostname, char** host, int* port) if (p) { - unsigned long val; - SSIZE_T length = (p - hostname); - errno = 0; - val = strtoul(p + 1, NULL, 0); + size_t length = (p - hostname); + LONGLONG val; - if ((errno != 0) || (val <= 0) || (val > UINT16_MAX)) + if (!value_to_int(p + 1, &val, 1, UINT16_MAX)) return FALSE; *host = (char*) calloc(length + 1UL, sizeof(char)); @@ -970,7 +1008,7 @@ BOOL freerdp_parse_hostname(const char* hostname, char** host, int* port) CopyMemory(*host, hostname, length); (*host)[length] = '\0'; - *port = val; + *port = (UINT16)val; } else { @@ -1509,13 +1547,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (p) { - unsigned long val = strtoul(&p[1], NULL, 0); + LONGLONG val; - if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + if (!value_to_int(&p[1], &val, 1, UINT16_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; length = (int)(p - arg->Value); - settings->ServerPort = val; + settings->ServerPort = (UINT16)val; if (!(settings->ServerHostname = (char*) calloc(length + 1UL, sizeof(char)))) return COMMAND_LINE_ERROR_MEMORY; @@ -1546,12 +1584,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (*(p2 + 1) == ':') { - unsigned long val = strtoul(&p2[2], NULL, 0); + LONGLONG val; - if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + if (!value_to_int(&p[2], &val, 0, UINT16_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->ServerPort = val; + settings->ServerPort = (UINT16)val; } printf("hostname %s port %"PRIu32"\n", settings->ServerHostname, settings->ServerPort); @@ -1618,21 +1656,21 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "w") { - long val = strtol(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val <= 0) || (val > UINT16_MAX)) + if (!value_to_int(arg->Value, &val, -1, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->DesktopWidth = val; + settings->DesktopWidth = (UINT32)val; } CommandLineSwitchCase(arg, "h") { - long val = strtol(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val <= 0) || (val > UINT16_MAX)) + if (!value_to_int(arg->Value, &val, -1, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->DesktopHeight = val; + settings->DesktopHeight = (UINT32)val; } CommandLineSwitchCase(arg, "size") { @@ -1679,15 +1717,15 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, *p = '\0'; { - long val = strtol(str, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val < 0) || (val > 100)) + if (!value_to_int(str, &val, 0, 100)) { free(str); return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } - settings->PercentScreen = val; + settings->PercentScreen = (UINT32)val; } } @@ -1737,12 +1775,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, for (i = 0; i < settings->NumMonitorIds; i++) { - unsigned long val = strtoul(p[i], NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > UINT16_MAX)) + if (!value_to_int(p[i], &val, 0, UINT16_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->MonitorIds[i] = val; + settings->MonitorIds[i] = (UINT32)val; } free(p); @@ -1795,13 +1833,11 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "bpp") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if (errno != 0) + if (!value_to_int(arg->Value, &val, 0, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->ColorDepth = val; - switch (settings->ColorDepth) { case 32: @@ -1809,6 +1845,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, case 16: case 15: case 8: + settings->ColorDepth = (UINT32)val; break; default: @@ -1843,9 +1880,9 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "kbd") { - unsigned long id = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (id > UINT32_MAX) || (id == 0)) + if (!value_to_int(arg->Value, &val, 1, UINT32_MAX)) { const int rc = freerdp_map_keyboard_layout_name_to_id(arg->Value); @@ -1857,38 +1894,38 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } /* Found a valid mapping, reset errno */ - id = (unsigned long)rc; + val = rc; errno = 0; } - settings->KeyboardLayout = (UINT32) id; + settings->KeyboardLayout = (UINT32) val; } CommandLineSwitchCase(arg, "kbd-type") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > UINT32_MAX)) + if (!value_to_int(arg->Value, &val, 0, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->KeyboardType = val; + settings->KeyboardType = (UINT32)val; } CommandLineSwitchCase(arg, "kbd-subtype") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > UINT32_MAX)) + if (!value_to_int(arg->Value, &val, 0, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->KeyboardSubType = val; + settings->KeyboardSubType = (UINT32)val; } CommandLineSwitchCase(arg, "kbd-fn-key") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > UINT32_MAX)) + if (!value_to_int(arg->Value, &val, 0, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->KeyboardFunctionKey = val; + settings->KeyboardFunctionKey = (UINT32)val; } CommandLineSwitchCase(arg, "u") { @@ -1914,19 +1951,20 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (p) { - unsigned long val = strtoul(&p[1], NULL, 0); + size_t s; + LONGLONG val; - if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + if (!value_to_int(&p[1], &val, 0, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - length = (int)(p - arg->Value); - settings->GatewayPort = val; + s = (p - arg->Value); + settings->GatewayPort = (UINT32)val; - if (!(settings->GatewayHostname = (char*) calloc(length + 1UL, sizeof(char)))) + if (!(settings->GatewayHostname = (char*) calloc(s + 1UL, sizeof(char)))) return COMMAND_LINE_ERROR_MEMORY; - strncpy(settings->GatewayHostname, arg->Value, length); - settings->GatewayHostname[length] = '\0'; + strncpy(settings->GatewayHostname, arg->Value, s); + settings->GatewayHostname[s] = '\0'; } else { @@ -2020,13 +2058,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (p) { - unsigned long val = strtoul(&p[1], NULL, 0); + LONGLONG val; - if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + if (!value_to_int(&p[1], &val, 0, UINT16_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; length = (p - arg->Value); - settings->ProxyPort = val; + settings->ProxyPort = (UINT16)val; settings->ProxyHostname = (char*) malloc(length + 1); strncpy(settings->ProxyHostname, arg->Value, length); settings->ProxyHostname[length] = '\0'; @@ -2084,8 +2122,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "gateway-usage-method") { - long type = 0; - char* pEnd; + UINT32 type = 0; if (_stricmp(arg->Value, "none") == 0) type = TSC_PROXY_MODE_NONE_DIRECT; @@ -2097,13 +2134,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, type = TSC_PROXY_MODE_DEFAULT; else { - type = strtol(arg->Value, &pEnd, 10); + LONGLONG val; - if (errno != 0) + if (!value_to_int(arg->Value, &val, TSC_PROXY_MODE_NONE_DIRECT, TSC_PROXY_MODE_NONE_DETECT)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } - freerdp_set_gateway_usage_method(settings, (UINT32) type); + freerdp_set_gateway_usage_method(settings, type); } CommandLineSwitchCase(arg, "app") { @@ -2155,12 +2192,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "compression-level") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > UINT32_MAX)) + if (!value_to_int(arg->Value, &val, 0, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->CompressionLevel = val; + settings->CompressionLevel = (UINT32)val; } CommandLineSwitchCase(arg, "drives") { @@ -2190,29 +2227,33 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "audio-mode") { - long mode = strtol(arg->Value, NULL, 0); + LONGLONG val; - if (errno != 0) + if (!value_to_int(arg->Value, &val, 0, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - if (mode == AUDIO_MODE_REDIRECT) + switch (val) { - settings->AudioPlayback = TRUE; - } - else if (mode == AUDIO_MODE_PLAY_ON_SERVER) - { - settings->RemoteConsoleAudio = TRUE; - } - else if (mode == AUDIO_MODE_NONE) - { - settings->AudioPlayback = FALSE; - settings->RemoteConsoleAudio = FALSE; + case AUDIO_MODE_REDIRECT: + settings->AudioPlayback = TRUE; + break; + + case AUDIO_MODE_PLAY_ON_SERVER: + settings->RemoteConsoleAudio = TRUE; + break; + + case AUDIO_MODE_NONE: + settings->AudioPlayback = FALSE; + settings->RemoteConsoleAudio = FALSE; + break; + + default: + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } } CommandLineSwitchCase(arg, "network") { - long type = 0; - char* pEnd; + int type = 0; if (_stricmp(arg->Value, "modem") == 0) type = CONNECTION_TYPE_MODEM; @@ -2234,10 +2275,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } else { - type = strtol(arg->Value, &pEnd, 10); + LONGLONG val; - if (errno != 0) + if (!value_to_int(arg->Value, &val, 1, 7)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + type = (int)val; } if (!freerdp_set_connection_type(settings, type)) @@ -2367,12 +2410,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "frame-ack") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > UINT32_MAX)) + if (!value_to_int(arg->Value, &val, 0, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->FrameAcknowledge = val; + settings->FrameAcknowledge = (UINT32)val; } CommandLineSwitchCase(arg, "nsc") { @@ -2386,12 +2429,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "jpeg-quality") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > 100)) + if (!value_to_int(arg->Value, &val, 0, 100)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->JpegQuality = val; + settings->JpegQuality = (UINT32)val; } #endif CommandLineSwitchCase(arg, "nego") @@ -2407,13 +2450,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "pcid") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > UINT32_MAX)) + if (!value_to_int(arg->Value, &val, 0, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; settings->SendPreconnectionPdu = TRUE; - settings->PreconnectionId = val; + settings->PreconnectionId = (UINT32)val; } CommandLineSwitchCase(arg, "sec") { @@ -2539,12 +2582,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "tls-seclevel") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > 5)) + if (!value_to_int(arg->Value, &val, 0, 5)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->TlsSecLevel = val; + settings->TlsSecLevel = (UINT32)val; } CommandLineSwitchCase(arg, "cert-name") { @@ -2589,12 +2632,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "parent-window") { - UINT64 val = _strtoui64(arg->Value, NULL, 0); + ULONGLONG val; - if (errno != 0) + if (!value_to_uint(arg->Value, &val, 0, UINT64_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->ParentWindowId = val; + settings->ParentWindowId = (UINT64)val; } CommandLineSwitchCase(arg, "bitmap-cache") { @@ -2640,32 +2683,24 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "max-fast-path-size") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > UINT32_MAX)) + if (!value_to_int(arg->Value, &val, 0, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->MultifragMaxRequestSize = val; + settings->MultifragMaxRequestSize = (UINT32)val; } CommandLineSwitchCase(arg, "max-loop-time") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > UINT32_MAX)) + if (!value_to_int(arg->Value, &val, -1, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->MaxTimeInCheckLoop = val; - - if ((long) settings->MaxTimeInCheckLoop < 0) - { - WLog_ERR(TAG, "invalid max loop time: %s", arg->Value); - return COMMAND_LINE_ERROR; - } - - if ((long) settings->MaxTimeInCheckLoop <= 0) - { + if (val < 0) settings->MaxTimeInCheckLoop = 10 * 60 * 60 * 1000; /* 10 hours can be considered as infinite */ - } + else + settings->MaxTimeInCheckLoop = (UINT32)val; } CommandLineSwitchCase(arg, "async-input") { @@ -2701,15 +2736,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "auto-reconnect-max-retries") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > UINT32_MAX)) + if (!value_to_int(arg->Value, &val, 0, 1000)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->AutoReconnectMaxRetries = val; - - if (settings->AutoReconnectMaxRetries > 1000) - return COMMAND_LINE_ERROR; + settings->AutoReconnectMaxRetries = (UINT32)val; } CommandLineSwitchCase(arg, "reconnect-cookie") { @@ -2735,30 +2767,30 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "pwidth") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > UINT32_MAX)) + if (!value_to_int(arg->Value, &val, 0, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->DesktopPhysicalWidth = val; + settings->DesktopPhysicalWidth = (UINT32)val; } CommandLineSwitchCase(arg, "pheight") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > UINT32_MAX)) + if (!value_to_int(arg->Value, &val, 0, UINT32_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->DesktopPhysicalHeight = val; + settings->DesktopPhysicalHeight = (UINT32)val; } CommandLineSwitchCase(arg, "orientation") { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val > INT16_MAX)) + if (!value_to_int(arg->Value, &val, 0, UINT16_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->DesktopOrientation = val; + settings->DesktopOrientation = (UINT16)val; } CommandLineSwitchCase(arg, "old-license") { @@ -2766,55 +2798,49 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "scale") { - unsigned long scaleFactor = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if (errno != 0) + if (!value_to_int(arg->Value, &val, 100, 180)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - if (scaleFactor == 100 || scaleFactor == 140 || scaleFactor == 180) + switch (val) { - settings->DesktopScaleFactor = scaleFactor; - settings->DeviceScaleFactor = scaleFactor; - } - else - { - WLog_ERR(TAG, "scale: invalid scale factor (%d)", scaleFactor); - return COMMAND_LINE_ERROR; + case 100: + case 140: + case 180: + settings->DeviceScaleFactor = (UINT32)val; + break; + + default: + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } } CommandLineSwitchCase(arg, "scale-desktop") { - unsigned long desktopScaleFactor = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if (errno != 0) - return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + if (!value_to_int(arg->Value, &val, 100, 500)) + return FALSE; - if (desktopScaleFactor >= 100 && desktopScaleFactor <= 500) - { - settings->DesktopScaleFactor = desktopScaleFactor; - } - else - { - WLog_ERR(TAG, "scale: invalid desktop scale factor (%d)", desktopScaleFactor); - return COMMAND_LINE_ERROR; - } + settings->DesktopScaleFactor = (UINT32)val; } CommandLineSwitchCase(arg, "scale-device") { - unsigned long deviceScaleFactor = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if (errno != 0) + if (!value_to_int(arg->Value, &val, 100, 180)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - if (deviceScaleFactor == 100 || deviceScaleFactor == 140 - || deviceScaleFactor == 180) + switch (val) { - settings->DeviceScaleFactor = deviceScaleFactor; - } - else - { - WLog_ERR(TAG, "scale: invalid device scale factor (%d)", deviceScaleFactor); - return COMMAND_LINE_ERROR; + case 100: + case 140: + case 180: + settings->DeviceScaleFactor = (UINT32)val; + break; + + default: + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } } CommandLineSwitchCase(arg, "action-script") @@ -2920,12 +2946,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT) { - unsigned long val = strtoul(arg->Value, NULL, 0); + LONGLONG val; - if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + if (!value_to_int(arg->Value, &val, 1, UINT16_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->ServerPort = val; + settings->ServerPort = (UINT32)val; } arg = CommandLineFindArgumentA(args, "p"); -- 2.7.4