diff --git a/src/protocols/rdp/rdp_fs.c b/src/protocols/rdp/rdp_fs.c index 6b9bf044..0e7345f9 100644 --- a/src/protocols/rdp/rdp_fs.c +++ b/src/protocols/rdp/rdp_fs.c @@ -607,66 +607,55 @@ const char* guac_rdp_fs_read_dir(guac_rdp_fs* fs, int file_id) { int guac_rdp_fs_normalize_path(const char* path, char* abs_path) { - int i; - - char path_component_data[GUAC_RDP_FS_MAX_PATH]; - const char* current_path_component_data = &(path_component_data[0]); - - /* Always include a blank path component at the beginning, such that the - * eventual call to guac_strljoin() will produce an absolute path (leading - * backslash) */ - int path_depth = 1; - const char* path_components[GUAC_RDP_MAX_PATH_DEPTH] = { "" }; + int path_depth = 0; + const char* path_components[GUAC_RDP_MAX_PATH_DEPTH]; /* If original path is not absolute, normalization fails */ if (path[0] != '\\' && path[0] != '/') return 1; - /* Skip past leading slash */ - path++; + /* Create scratch copy of path excluding leading slash (we will be + * replacing path separators with null terminators and referencing those + * substrings directly as path components) */ + char path_scratch[GUAC_RDP_FS_MAX_PATH - 1]; + int length = guac_strlcpy(path_scratch, path + 1, + sizeof(path_scratch)); - /* Copy path into component data for parsing */ - int length = guac_strlcpy(path_component_data, path, - sizeof(path_component_data)); - - /* Fail if input path was truncated */ - if (length >= sizeof(path_component_data)) + /* Fail if provided path is too long */ + if (length >= sizeof(path_scratch)) return 1; - /* Find path components within path */ - for (i = 0; i < sizeof(path_component_data); i++) { + /* Locate all path components within path */ + const char* current_path_component = &(path_scratch[0]); + for (int i = 0; i <= length; i++) { /* If current character is a path separator, parse as component */ - char c = path_component_data[i]; - if (c == '/' || c == '\\' || c == 0) { + char c = path_scratch[i]; + if (c == '/' || c == '\\' || c == '\0') { /* Terminate current component */ - path_component_data[i] = 0; + path_scratch[i] = '\0'; /* If component refers to parent, just move up in depth */ - if (strcmp(current_path_component_data, "..") == 0) { - if (path_depth > 1) + if (strcmp(current_path_component, "..") == 0) { + if (path_depth > 0) path_depth--; } /* Otherwise, if component not current directory, add to list */ - else if (strcmp(current_path_component_data, ".") != 0 - && strcmp(current_path_component_data, "") != 0) { + else if (strcmp(current_path_component, ".") != 0 + && strcmp(current_path_component, "") != 0) { /* Fail normalization if path is too deep */ if (path_depth >= GUAC_RDP_MAX_PATH_DEPTH) return 1; - path_components[path_depth++] = current_path_component_data; + path_components[path_depth++] = current_path_component; } - /* If end of string, stop */ - if (c == 0) - break; - /* Update start of next component */ - current_path_component_data = &(path_component_data[i+1]); + current_path_component = &(path_scratch[i+1]); } /* end if separator */ @@ -676,15 +665,12 @@ int guac_rdp_fs_normalize_path(const char* path, char* abs_path) { } /* end for each character */ - /* If no components, the path is simply root */ - if (path_depth == 0) { - strcpy(abs_path, "\\"); - return 0; - } + /* Add leading slash for resulting absolute path */ + abs_path[0] = '\\'; - /* Convert components back into path */ - guac_strljoin(abs_path, path_components, path_depth, - "\\", GUAC_RDP_FS_MAX_PATH); + /* Append normalized components to path, separated by slashes */ + guac_strljoin(abs_path + 1, path_components, path_depth, + "\\", GUAC_RDP_FS_MAX_PATH - 1); return 0;