Merge branch 'reimplement-pathonly'
MSW builds / wxMSW vs2022 DLL Debug x64 (push) Has been cancelled
MSW builds / wxMSW vs2022 DLL Release x64 (push) Has been cancelled
MSW builds / wxMSW vs2022 Debug Win32 (push) Has been cancelled
MSW builds / wxMSW vs2022 Release arm64 (push) Has been cancelled
MSW builds / wxMSW vs2026 DLL Release x64 (push) Has been cancelled
MSW cross-builds / wxMSW 64 bits not compatible (push) Has been cancelled
MSW cross-builds / wxMSW/Univ (push) Has been cancelled
MSW cross-builds / wxMSW 32 bits (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxGTK 3 compatible 3.0 (push) Has been cancelled
Unix builds / Ubuntu 24.04 wxGTK ASAN not compatible (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxGTK UTF-8 (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxQt (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxX11 (push) Has been cancelled
Unix builds / Ubuntu 20.04 wxGTK 3 with clang (push) Has been cancelled
Unix builds / Ubuntu 22.04 wxGTK with wx containers (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxDFB (push) Has been cancelled
Unix builds / Ubuntu 24.04 wxGTK UBSAN (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxGTK 3 static with gcc 4.8 (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxGTK 2 (push) Has been cancelled
CMake builds / Ubuntu 22.04 wxGTK 3 (push) Has been cancelled
CMake builds / macOS latest wxGTK 3 Unix Makefiles (push) Has been cancelled
CMake builds / MSW/MSVC wxMSW (push) Has been cancelled
CMake builds / MSW/Clang wxMSW (push) Has been cancelled
CMake builds / macOS latest wxOSX Ninja (push) Has been cancelled
CMake builds / macOS 14 wxOSX Xcode (push) Has been cancelled
CMake builds / macOS 14 wxIOS (push) Has been cancelled
CMake builds / MSW/MSVC wxQt 5.15 (push) Has been cancelled
CMake builds / MSW/MSVC wxQt 6.10 (push) Has been cancelled
Mac builds / wxMac ARM ASAN not compatible (push) Has been cancelled
Mac builds / wxMac Universal C++14 (push) Has been cancelled
Mac builds / wxiOS Simulator on Silicon Mac (push) Has been cancelled
Mac builds / wxiOS (push) Has been cancelled
Mac builds / wxMac Intel C++17 (push) Has been cancelled
Mac Xcode builds / iOS Simulator static (push) Has been cancelled
Mac Xcode builds / macOS dynamic Release (push) Has been cancelled
Mac Xcode builds / iOS static Debug (push) Has been cancelled
Code Checks / Check Spelling (push) Has been cancelled
Code Checks / Check Whitespace (push) Has been cancelled
Code Checks / Check Mixed EOL (push) Has been cancelled
Code Checks / Check C++ Style (push) Has been cancelled
Code Checks / Check All Headers In allheaders.h (push) Has been cancelled
Update Documentation / Update Online Documentation (push) Has been cancelled

Reimplement wxPathOnly() using wxFileName::GetPath().

This incidentally fixes a buffer overflow in this function, see #26526.

See #26537.
This commit is contained in:
Vadim Zeitlin
2026-05-31 15:46:24 +02:00
3 changed files with 45 additions and 92 deletions
+13
View File
@@ -294,6 +294,19 @@ wxString wxGetWorkingDirectory(char* buf = nullptr, int sz = 1000);
/**
Returns the directory part of the filename.
@deprecated Please use wxFileName::GetPath() instead.
Note that the behaviour of this function is slightly different for Windows
paths including drive letters: it returns a string without trailing
backslash for the absolute paths with drive letters and a string with
trailing dot for the relative paths with drive letters.
Since wxWidgets 3.3.3 all path separators are normalized to the current
platform path separator in the returned path, i.e. under Windows forward
slashes in @a path will be replaced with backslashes in the returned value.
Previous versions of wxWidgets didn't perform this normalization and
returned the path with the same separators as in @a path.
@header{wx/filefn.h}
*/
wxString wxPathOnly(const wxString& path);
+21 -92
View File
@@ -261,105 +261,34 @@ wxString wxFileNameFromPath (const wxString& path)
return wxFileName(path).GetFullName();
}
// Return just the directory, or nullptr if no directory
wxChar *
wxPathOnly (wxChar *path)
{
if (path && *path)
{
static wxChar buf[_MAXPATHLEN];
int l = wxStrlen(path);
int i = l - 1;
if ( i >= _MAXPATHLEN )
return nullptr;
// Local copy
wxStrcpy (buf, path);
// Search backward for a backward or forward slash
while (i > -1)
{
// Unix like or Windows
if (path[i] == wxT('/') || path[i] == wxT('\\'))
{
buf[i] = 0;
return buf;
}
#ifdef __VMS__
if (path[i] == wxT(']'))
{
buf[i+1] = 0;
return buf;
}
#endif
i --;
}
#if defined(__WINDOWS__)
// Try Drive specifier
if (wxIsalpha (buf[0]) && buf[1] == wxT(':'))
{
// A:junk --> A:. (since A:.\junk Not A:\junk)
buf[2] = wxT('.');
buf[3] = wxT('\0');
return buf;
}
#endif
}
return nullptr;
}
// Return just the directory, or nullptr if no directory
// Return just the directory, or empty string if no directory
wxString wxPathOnly (const wxString& path)
{
if (!path.empty())
{
wxChar buf[_MAXPATHLEN];
int l = path.length();
int i = l - 1;
if ( i >= _MAXPATHLEN )
return wxString();
// Local copy
wxStrcpy(buf, path);
// Search backward for a backward or forward slash
while (i > -1)
{
// Unix like or Windows
if (path[i] == wxT('/') || path[i] == wxT('\\'))
{
// Don't return an empty string
if (i == 0)
i ++;
buf[i] = 0;
return wxString(buf);
}
#ifdef __VMS__
if (path[i] == wxT(']'))
{
buf[i+1] = 0;
return wxString(buf);
}
#endif
i --;
}
wxString res = wxFileName(path).GetPath();
// For compatibility with the old behaviour of this function, we need to
// return "X:" for paths with volume and absolute path under Windows and
// "X:." for paths with volume and relative path.
#if defined(__WINDOWS__)
// Try Drive specifier
if (wxIsalpha (buf[0]) && buf[1] == wxT(':'))
if ( res.size() >= 2 && wxIsalpha(res[0]) && res[1] == wxT(':') )
{
switch ( res.size() )
{
// A:junk --> A:. (since A:.\junk Not A:\junk)
buf[2] = wxT('.');
buf[3] = wxT('\0');
return wxString(buf);
case 2:
// "X:" --> "X:."
res += wxT('.');
break;
case 3:
// "X:\" --> "X:"
if ( res[2] == wxFILE_SEP_PATH )
res.erase(2);
break;
}
#endif
}
return wxEmptyString;
#endif // __WINDOWS__
return res;
}
// Utility for converting delimiters in DOS filenames to UNIX style
+11
View File
@@ -488,6 +488,17 @@ TEST_CASE_METHOD(FileFunctionsTestCase,
wxString pathOnly = wxPathOnly(filename.GetFullPath());
if ( !wxDirExists(pathOnly) )
CHECK( pathOnly == wxString() );
CHECK( wxPathOnly(wxString{}) == "" );
CHECK( wxPathOnly("foo") == "" );
CHECK( wxPathOnly("foo/") == "foo" );
CHECK( wxPathOnly("/foo/") == wxString(wxFILE_SEP_PATH) + "foo" );
#ifdef __WINDOWS__
CHECK( wxPathOnly("c:\\foo.exe") == "c:" );
CHECK( wxPathOnly("c:foo.exe") == "c:." );
CHECK( wxPathOnly("foo\\bar.dll") == "foo" );
#endif
}
// Unit tests for Mkdir and Rmdir doesn't cover non-ASCII directory names.