From 64c0ca14a3af7feaab38e2db484d516d1d9f67c3 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Thu, 24 Dec 2020 19:36:58 -0800 Subject: [PATCH] System: Fix some bugs in GetTitleForPath The previous implementation had a few issues in certain edge cases: - If the path contained no '/' or '\', then the string_view constructor is called with a count that exceeds the length of the string (effectively `title_end - (char *)0`, which is undefined behavior, at least in C). - If the only '/' was the filesystem root, the last character of the title was truncated, and the '/' remained. For example, "/title.bin" resulted in "/titl". - At least in C, it is undefined behavior to use the the < operator with a null pointer, which is done in std::max if the path did not have both '/' and '\'. The first issue results in a std::bad_alloc exception on my machine. --- src/core/system.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/core/system.cpp b/src/core/system.cpp index 00fd74ffc..b17c3e3a6 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -314,17 +314,11 @@ ConsoleRegion GetConsoleRegionForDiscRegion(DiscRegion region) std::string_view GetTitleForPath(const char* path) { - const char* extension = std::strrchr(path, '.'); - if (path == extension) - return path; - - const char* path_end = path + std::strlen(path); - const char* title_end = extension ? (extension - 1) : (path_end); - const char* title_start = std::max(std::strrchr(path, '/'), std::strrchr(path, '\\')); - if (!title_start || title_start == path) - return std::string_view(path, title_end - title_start); - else - return std::string_view(title_start + 1, title_end - title_start); + std::string_view path_view = path; + std::size_t title_start = path_view.find_last_of("/\\"); + if (title_start != std::string_view::npos) + path_view.remove_prefix(title_start + 1); + return path_view.substr(0, path_view.find_last_of('.')); } std::string GetGameCodeForPath(const char* image_path)