summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--desktop/win32/source/loader.cxx203
-rw-r--r--desktop/win32/source/unoinfo.cxx9
-rw-r--r--include/tools/pathutils.hxx20
-rw-r--r--pyuno/zipcore/python.cxx60
-rw-r--r--tools/qa/cppunit/test_pathutils.cxx8
-rw-r--r--tools/source/misc/pathutils.cxx59
6 files changed, 141 insertions, 218 deletions
diff --git a/desktop/win32/source/loader.cxx b/desktop/win32/source/loader.cxx
index bbc97a462724..b51475430911 100644
--- a/desktop/win32/source/loader.cxx
+++ b/desktop/win32/source/loader.cxx
@@ -33,9 +33,6 @@
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
-#define MY_LENGTH(s) (std::size(s) - 1)
-#define MY_STRING(s) (s), MY_LENGTH(s)
-
namespace {
void fail()
@@ -85,9 +82,10 @@ std::wstring getCWDarg()
{
std::wstring s(L" \"-env:OOO_CWD=");
- WCHAR cwd[MAX_PATH];
- DWORD cwdLen = GetCurrentDirectoryW(MAX_PATH, cwd);
- if (cwdLen == 0 || cwdLen >= MAX_PATH)
+ DWORD cwdLen = GetCurrentDirectoryW(0, nullptr);
+ std::vector<WCHAR> cwd(cwdLen);
+ cwdLen = GetCurrentDirectoryW(cwdLen, cwd.data());
+ if (cwdLen == 0 || cwdLen >= cwd.size())
{
s += L'0';
}
@@ -96,7 +94,7 @@ std::wstring getCWDarg()
s += L'2';
size_t n = 0; // number of trailing backslashes
- for (auto* p = cwd; *p; ++p)
+ for (auto* p = cwd.data(); *p; ++p)
{
WCHAR c = *p;
if (c == L'$')
@@ -132,26 +130,30 @@ WCHAR* commandLineAppend(WCHAR* buffer, std::wstring_view text)
// Set the PATH environment variable in the current (loader) process, so that a
// following CreateProcess has the necessary environment:
-// @param binPath
-// Must point to an array of size at least MAX_PATH. Is filled with the null
-// terminated full path to the "bin" file corresponding to the current
-// executable.
-// @param iniDirectory
-// Must point to an array of size at least MAX_PATH. Is filled with the null
-// terminated full directory path (ending in "\") to the "ini" file
-// corresponding to the current executable.
-void extendLoaderEnvironment(WCHAR * binPath, WCHAR * iniDirectory) {
- if (!GetModuleFileNameW(nullptr, iniDirectory, MAX_PATH)) {
- fail();
- }
- WCHAR * iniDirEnd = tools::filename(iniDirectory);
- WCHAR name[MAX_PATH + MY_LENGTH(L".bin")];
- // hopefully std::size_t is large enough to not overflow
- WCHAR * nameEnd = name;
- for (WCHAR * p = iniDirEnd; *p != L'\0'; ++p) {
- *nameEnd++ = *p;
+// returns a pair of strings { binPath, iniDirectory }
+// * binPath is the full path to the "bin" file corresponding to the current executable.
+// * iniDirectory is the full directory path (ending in "\") to the "ini" file corresponding to the
+// current executable.
+[[nodiscard]] std::pair<std::wstring, std::wstring> extendLoaderEnvironment()
+{
+ std::vector<wchar_t> executable_path(MAX_PATH);
+ DWORD exe_len;
+ for (;;)
+ {
+ exe_len = GetModuleFileNameW(nullptr, executable_path.data(), executable_path.size());
+ if (!exe_len)
+ fail();
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ executable_path.resize(exe_len + 4); // to accomodate a possible ".bin" in the end
+ break;
+ }
+ executable_path.resize(executable_path.size() * 2);
}
- if (!(nameEnd - name >= 4 && nameEnd[-4] == L'.' &&
+ WCHAR* iniDirEnd = tools::filename(executable_path.data());
+ std::wstring_view iniDirView(executable_path.data(), iniDirEnd);
+ WCHAR* nameEnd = executable_path.data() + exe_len;
+ if (!(nameEnd - iniDirEnd >= 4 && nameEnd[-4] == L'.' &&
(((nameEnd[-3] == L'E' || nameEnd[-3] == L'e') &&
(nameEnd[-2] == L'X' || nameEnd[-2] == L'x') &&
(nameEnd[-1] == L'E' || nameEnd[-1] == L'e')) ||
@@ -165,30 +167,30 @@ void extendLoaderEnvironment(WCHAR * binPath, WCHAR * iniDirectory) {
nameEnd[-3] = 'b';
nameEnd[-2] = 'i';
nameEnd[-1] = 'n';
- tools::buildPath(binPath, iniDirectory, iniDirEnd, name, nameEnd - name);
- *iniDirEnd = L'\0';
- std::size_t const maxEnv = 32767;
- WCHAR env[maxEnv];
- DWORD n = GetEnvironmentVariableW(L"PATH", env, maxEnv);
- if ((n >= maxEnv || n == 0) && GetLastError() != ERROR_ENVVAR_NOT_FOUND) {
+ std::wstring_view nameView(iniDirEnd, nameEnd);
+
+ WCHAR env[32767];
+ DWORD n = GetEnvironmentVariableW(L"PATH", env, std::size(env));
+ if ((n >= std::size(env) || n == 0) && GetLastError() != ERROR_ENVVAR_NOT_FOUND) {
fail();
}
+ std::wstring_view envView(env, n);
// must be first in PATH to override other entries
- assert(*(iniDirEnd - 1) == L'\\'); // hence -1 below
- std::wstring_view iniDirView(iniDirectory, iniDirEnd - iniDirectory - 1);
- if (!std::wstring_view(env, n).starts_with(iniDirView) || env[iniDirView.size()] != L';')
+ assert(iniDirView.back() == L'\\'); // hence -1 below
+ std::wstring_view iniDirView1(iniDirView.substr(0, iniDirView.size() - 1));
+ if (!envView.starts_with(iniDirView1) || env[iniDirView1.size()] != L';')
{
- WCHAR pad[MAX_PATH + maxEnv];
- // hopefully std::size_t is large enough to not overflow
- WCHAR* p = commandLineAppend(pad, iniDirView);
+ std::wstring pad(iniDirView1);
if (n != 0) {
- *p++ = L';';
- commandLineAppend(p, std::wstring_view(env, n));
+ pad += L';';
+ pad += envView;
}
- if (!SetEnvironmentVariableW(L"PATH", pad)) {
+ if (!SetEnvironmentVariableW(L"PATH", pad.data())) {
fail();
}
}
+
+ return { tools::buildPath(iniDirView, nameView), std::wstring(iniDirView) };
}
}
@@ -197,10 +199,7 @@ namespace desktop_win32 {
int officeloader_impl(bool bAllowConsole)
{
- WCHAR szTargetFileName[MAX_PATH] = {};
- WCHAR szIniDirectory[MAX_PATH];
-
- extendLoaderEnvironment(szTargetFileName, szIniDirectory);
+ const auto& [szTargetFileName, szIniDirectory] = extendLoaderEnvironment();
STARTUPINFOW aStartupInfo;
ZeroMemory(&aStartupInfo, sizeof(aStartupInfo));
@@ -221,57 +220,39 @@ int officeloader_impl(bool bAllowConsole)
bool fallbackForMaxMemoryInMB = true;
bool fallbackForExcludeChildProcesses = true;
- const WCHAR* szIniFile = L"\\fundamental.override.ini";
- const size_t nDirLen = wcslen(szIniDirectory);
- if (wcslen(szIniFile) + nDirLen < MAX_PATH)
+ try
{
- WCHAR szBootstrapIni[MAX_PATH];
- wcscpy(szBootstrapIni, szIniDirectory);
- wcscpy(&szBootstrapIni[nDirLen], szIniFile);
-
- try
- {
- boost::property_tree::ptree pt;
- std::ifstream aFile(szBootstrapIni);
- boost::property_tree::ini_parser::read_ini(aFile, pt);
- nMaxMemoryInMB = pt.get("Bootstrap.LimitMaximumMemoryInMB", nMaxMemoryInMB);
- fallbackForMaxMemoryInMB = !pt.get_child_optional("Bootstrap.LimitMaximumMemoryInMB");
- bExcludeChildProcesses = pt.get("Bootstrap.ExcludeChildProcessesFromLimit", bExcludeChildProcesses);
- fallbackForExcludeChildProcesses
- = !pt.get_child_optional("Bootstrap.ExcludeChildProcessesFromLimit");
- }
- catch (...)
- {
- nMaxMemoryInMB = 0;
- }
+ boost::property_tree::ptree pt;
+ std::ifstream aFile(szIniDirectory + L"\\fundamental.override.ini");
+ boost::property_tree::ini_parser::read_ini(aFile, pt);
+ nMaxMemoryInMB = pt.get("Bootstrap.LimitMaximumMemoryInMB", nMaxMemoryInMB);
+ fallbackForMaxMemoryInMB = !pt.get_child_optional("Bootstrap.LimitMaximumMemoryInMB");
+ bExcludeChildProcesses = pt.get("Bootstrap.ExcludeChildProcessesFromLimit", bExcludeChildProcesses);
+ fallbackForExcludeChildProcesses
+ = !pt.get_child_optional("Bootstrap.ExcludeChildProcessesFromLimit");
+ }
+ catch (...)
+ {
+ nMaxMemoryInMB = 0;
}
// For backwards compatibility, for now also try to read the values from bootstrap.ini if
// fundamental.override.ini does not provide them:
if (fallbackForMaxMemoryInMB || fallbackForExcludeChildProcesses) {
- const WCHAR* szFallbackIniFile = L"\\bootstrap.ini";
- const size_t nFallbackDirLen = wcslen(szIniDirectory);
- if (wcslen(szFallbackIniFile) + nFallbackDirLen < MAX_PATH)
+ try
{
- WCHAR szBootstrapIni[MAX_PATH];
- wcscpy(szBootstrapIni, szIniDirectory);
- wcscpy(&szBootstrapIni[nFallbackDirLen], szFallbackIniFile);
-
- try
- {
- boost::property_tree::ptree pt;
- std::ifstream aFile(szBootstrapIni);
- boost::property_tree::ini_parser::read_ini(aFile, pt);
- if (fallbackForMaxMemoryInMB) {
- nMaxMemoryInMB = pt.get("Win32.LimitMaximumMemoryInMB", nMaxMemoryInMB);
- }
- if (fallbackForExcludeChildProcesses) {
- bExcludeChildProcesses = pt.get("Win32.ExcludeChildProcessesFromLimit", bExcludeChildProcesses);
- }
+ boost::property_tree::ptree pt;
+ std::ifstream aFile(szIniDirectory + L"\\bootstrap.ini");
+ boost::property_tree::ini_parser::read_ini(aFile, pt);
+ if (fallbackForMaxMemoryInMB) {
+ nMaxMemoryInMB = pt.get("Win32.LimitMaximumMemoryInMB", nMaxMemoryInMB);
}
- catch (...)
- {
+ if (fallbackForExcludeChildProcesses) {
+ bExcludeChildProcesses = pt.get("Win32.ExcludeChildProcessesFromLimit", bExcludeChildProcesses);
}
}
+ catch (...)
+ {
+ }
}
// create a Windows JobObject with a memory limit
@@ -355,9 +336,9 @@ int officeloader_impl(bool bAllowConsole)
PROCESS_INFORMATION aProcessInfo;
- fSuccess = CreateProcessW(szTargetFileName, lpCommandLine, nullptr, nullptr, TRUE,
- bAllowConsole ? 0 : DETACHED_PROCESS, nullptr, szIniDirectory,
- &aStartupInfo, &aProcessInfo);
+ fSuccess = CreateProcessW(szTargetFileName.data(), lpCommandLine, nullptr, nullptr, TRUE,
+ bAllowConsole ? 0 : DETACHED_PROCESS, nullptr,
+ szIniDirectory.data(), &aStartupInfo, &aProcessInfo);
if (fSuccess)
{
@@ -402,9 +383,7 @@ int officeloader_impl(bool bAllowConsole)
int unopkgloader_impl(bool bAllowConsole)
{
- WCHAR szTargetFileName[MAX_PATH];
- WCHAR szIniDirectory[MAX_PATH];
- extendLoaderEnvironment(szTargetFileName, szIniDirectory);
+ const auto& [szTargetFileName, szIniDirectory] = extendLoaderEnvironment();
STARTUPINFOW aStartupInfo{};
aStartupInfo.cb = sizeof(aStartupInfo);
@@ -412,50 +391,32 @@ int unopkgloader_impl(bool bAllowConsole)
DWORD dwExitCode = DWORD(-1);
- size_t iniDirLen = wcslen(szIniDirectory);
std::wstring sCWDarg = getCWDarg();
- WCHAR redirect[MAX_PATH];
DWORD dummy;
- bool hasRedirect =
- tools::buildPath(
- redirect, szIniDirectory, szIniDirectory + iniDirLen,
- MY_STRING(L"redirect.ini")) != nullptr &&
- (GetBinaryTypeW(redirect, &dummy) || // cheaper check for file existence?
+ std::wstring redirect = tools::buildPath(szIniDirectory, L"redirect.ini");
+ bool hasRedirect = !redirect.empty() &&
+ (GetBinaryTypeW(redirect.data(), &dummy) || // cheaper check for file existence?
GetLastError() != ERROR_FILE_NOT_FOUND);
LPWSTR cl1 = GetCommandLineW();
- WCHAR* cl2 = new WCHAR[
- wcslen(cl1) +
- (hasRedirect
- ? (MY_LENGTH(L" \"-env:INIFILENAME=vnd.sun.star.pathname:") +
- iniDirLen + MY_LENGTH(L"redirect.ini\""))
- : 0) +
- sCWDarg.size() + 1];
- // 4 * cwdLen: each char preceded by backslash, each trailing backslash
- // doubled
- WCHAR* p = commandLineAppend(cl2, cl1);
- if (hasRedirect) {
- p = commandLineAppend(p, L" \"-env:INIFILENAME=vnd.sun.star.pathname:");
- p = commandLineAppend(p, szIniDirectory);
- p = commandLineAppend(p, L"redirect.ini\"");
- }
- commandLineAppend(p, sCWDarg);
+ std::wstring cl2 = cl1;
+ if (hasRedirect)
+ cl2 += L" \"-env:INIFILENAME=vnd.sun.star.pathname:" + redirect + L"\"";
+ cl2 += sCWDarg;
PROCESS_INFORMATION aProcessInfo;
bool fSuccess = CreateProcessW(
- szTargetFileName,
- cl2,
+ szTargetFileName.data(),
+ cl2.data(),
nullptr,
nullptr,
TRUE,
bAllowConsole ? 0 : DETACHED_PROCESS,
nullptr,
- szIniDirectory,
+ szIniDirectory.data(),
&aStartupInfo,
&aProcessInfo);
- delete[] cl2;
-
if (fSuccess)
{
DWORD dwWaitResult;
diff --git a/desktop/win32/source/unoinfo.cxx b/desktop/win32/source/unoinfo.cxx
index 14cee8819dde..28a91b41547d 100644
--- a/desktop/win32/source/unoinfo.cxx
+++ b/desktop/win32/source/unoinfo.cxx
@@ -50,14 +50,11 @@ void writePath(
wchar_t const * frontBegin, wchar_t const * frontEnd,
wchar_t const * backBegin, std::size_t backLength)
{
- wchar_t path[MAX_PATH];
- wchar_t * end = tools::buildPath(
- path, frontBegin, frontEnd, backBegin, backLength);
- if (end == nullptr) {
+ std::wstring path = tools::buildPath({ frontBegin, frontEnd }, { backBegin, backLength });
+ if (path.empty()) {
exit(EXIT_FAILURE);
}
- std::size_t n = (end - path) * sizeof (wchar_t);
- if (fwrite(path, 1, n, stdout) != n) {
+ if (fwrite(path.data(), sizeof (wchar_t), path.size(), stdout) != path.size()) {
exit(EXIT_FAILURE);
}
}
diff --git a/include/tools/pathutils.hxx b/include/tools/pathutils.hxx
index 045ec4b96bbe..26696da39260 100644
--- a/include/tools/pathutils.hxx
+++ b/include/tools/pathutils.hxx
@@ -21,6 +21,9 @@
#include <sal/config.h>
+#include <string>
+#include <string_view>
+
#if defined(_WIN32)
#include <cstddef>
#define WIN32_LEAN_AND_MEAN
@@ -49,21 +52,14 @@ WCHAR* filename(WCHAR* path);
as there are no symbolic links on Windows (as with symbolic links, x\y\.. and
x might denote different directories).
- @param path
- An output parameter taking the resulting path; must point at a valid
- range of memory of size at least MAX_PATH. If NULL is returned, the
- content is unspecified.
- @param frontBegin, frontEnd
- Forms a valid range [frontBegin .. frontEnd) of less than MAX_PATH size.
+ @param front
+ First path
@param backBegin, backLength
- Forms a valid range [backBegin .. backBegin + backLength) of less than
- MAX_PATH size.
+ Second path
@return
- A pointer to the terminating null character of the concatenation, or NULL
- if a failure occurred.
+ The concatenation, empty if a failure occurred.
*/
-WCHAR* buildPath(WCHAR* path, WCHAR const* frontBegin, WCHAR const* frontEnd,
- WCHAR const* backBegin, std::size_t backLength);
+std::wstring buildPath(std::wstring_view front, std::wstring_view back);
}
#endif
diff --git a/pyuno/zipcore/python.cxx b/pyuno/zipcore/python.cxx
index 7580e32789e3..b4f3149be128 100644
--- a/pyuno/zipcore/python.cxx
+++ b/pyuno/zipcore/python.cxx
@@ -79,42 +79,36 @@ int wmain(int argc, wchar_t ** argv, wchar_t **) {
exit(EXIT_FAILURE);
}
}
- wchar_t bootstrap[MY_LENGTH(L"vnd.sun.star.pathname:") + MAX_PATH] =
- L"vnd.sun.star.pathname:"; //TODO: overflow
- wchar_t * bootstrapEnd = tools::buildPath(
- bootstrap + MY_LENGTH(L"vnd.sun.star.pathname:"), path, pathEnd,
- MY_STRING(L"fundamental.ini"));
- if (bootstrapEnd == nullptr) {
+ std::wstring bootstrap = tools::buildPath({ path, pathEnd }, L"fundamental.ini");
+ if (bootstrap.empty()) {
exit(EXIT_FAILURE);
}
- wchar_t pythonpath2[MAX_PATH];
- wchar_t * pythonpath2End = tools::buildPath(
- pythonpath2, path, pathEnd,
- MY_STRING(L"\\python-core-" PYTHON_VERSION_STRING L"\\lib"));
- if (pythonpath2End == nullptr) {
+ bootstrap = L"vnd.sun.star.pathname:" + bootstrap;
+ std::wstring pythonpath2 = tools::buildPath(
+ { path, pathEnd },
+ L"\\python-core-" PYTHON_VERSION_STRING L"\\lib");
+ if (pythonpath2.empty()) {
exit(EXIT_FAILURE);
}
- wchar_t pythonpath3[MAX_PATH];
- wchar_t * pythonpath3End = tools::buildPath(
- pythonpath3, path, pathEnd,
- MY_STRING(L"\\python-core-" PYTHON_VERSION_STRING L"\\lib\\site-packages"));
- if (pythonpath3End == nullptr) {
+ std::wstring pythonpath3 = tools::buildPath(
+ { path, pathEnd },
+ L"\\python-core-" PYTHON_VERSION_STRING L"\\lib\\site-packages");
+ if (pythonpath3.empty()) {
exit(EXIT_FAILURE);
}
- wchar_t pythonhome[MAX_PATH];
- wchar_t * pythonhomeEnd = tools::buildPath(
- pythonhome, path, pathEnd, MY_STRING(L"\\python-core-" PYTHON_VERSION_STRING));
- if (pythonhomeEnd == nullptr) {
+ std::wstring pythonhome = tools::buildPath(
+ { path, pathEnd },
+ L"\\python-core-" PYTHON_VERSION_STRING);
+ if (pythonhome.empty()) {
exit(EXIT_FAILURE);
}
- wchar_t pythonexe[MAX_PATH];
- wchar_t * pythonexeEnd = tools::buildPath(
- pythonexe, path, pathEnd,
- MY_STRING(L"\\python-core-" PYTHON_VERSION_STRING L"\\bin\\python.exe"));
- if (pythonexeEnd == nullptr) {
+ std::wstring pythonexe = tools::buildPath(
+ { path, pathEnd },
+ L"\\python-core-" PYTHON_VERSION_STRING L"\\bin\\python.exe");
+ if (pythonexe.empty()) {
exit(EXIT_FAILURE);
}
- std::size_t clSize = MY_LENGTH(L"\"") + 4 * (pythonexeEnd - pythonexe) +
+ std::size_t clSize = MY_LENGTH(L"\"") + 4 * pythonexe.size() +
MY_LENGTH(L"\"\0"); //TODO: overflow
// 4 * len: each char preceded by backslash, each trailing backslash
// doubled
@@ -123,7 +117,7 @@ int wmain(int argc, wchar_t ** argv, wchar_t **) {
//TODO: overflow
}
wchar_t * cl = new wchar_t[clSize];
- wchar_t * cp = encode(cl, pythonhome);
+ wchar_t * cp = encode(cl, pythonhome.data());
for (int i = 1; i < argc; ++i) {
*cp++ = L' ';
cp = encode(cp, argv[i]);
@@ -169,12 +163,12 @@ int wmain(int argc, wchar_t ** argv, wchar_t **) {
exit(EXIT_FAILURE);
}
}
- len = (pathEnd - path) + MY_LENGTH(L";") + (pythonpath2End - pythonpath2) +
- MY_LENGTH(L";") + (pythonpath3End - pythonpath3) +
+ len = (pathEnd - path) + MY_LENGTH(L";") + pythonpath2.size() +
+ MY_LENGTH(L";") + pythonpath3.size() +
(n == 0 ? 0 : MY_LENGTH(L";") + (n - 1)) + 1; //TODO: overflow
value = new wchar_t[len];
_snwprintf(
- value, len, L"%s;%s;%s%s%s", path, pythonpath2, pythonpath3,
+ value, len, L"%s;%s;%s%s%s", path, pythonpath2.c_str(), pythonpath3.c_str(),
n == 0 ? L"" : L";", orig);
if (!SetEnvironmentVariableW(L"PYTHONPATH", value)) {
exit(EXIT_FAILURE);
@@ -183,13 +177,13 @@ int wmain(int argc, wchar_t ** argv, wchar_t **) {
delete [] orig;
}
delete [] value;
- if (!SetEnvironmentVariableW(L"PYTHONHOME", pythonhome)) {
+ if (!SetEnvironmentVariableW(L"PYTHONHOME", pythonhome.data())) {
exit(EXIT_FAILURE);
}
n = GetEnvironmentVariableW(L"URE_BOOTSTRAP", nullptr, 0);
if (n == 0) {
if (GetLastError() != ERROR_ENVVAR_NOT_FOUND ||
- !SetEnvironmentVariableW(L"URE_BOOTSTRAP", bootstrap))
+ !SetEnvironmentVariableW(L"URE_BOOTSTRAP", bootstrap.data()))
{
exit(EXIT_FAILURE);
}
@@ -199,7 +193,7 @@ int wmain(int argc, wchar_t ** argv, wchar_t **) {
startinfo.cb = sizeof (STARTUPINFOW);
PROCESS_INFORMATION procinfo;
if (!CreateProcessW(
- pythonexe, cl, nullptr, nullptr, FALSE, CREATE_UNICODE_ENVIRONMENT, nullptr,
+ pythonexe.data(), cl, nullptr, nullptr, FALSE, CREATE_UNICODE_ENVIRONMENT, nullptr,
nullptr, &startinfo, &procinfo)) {
exit(EXIT_FAILURE);
}
diff --git a/tools/qa/cppunit/test_pathutils.cxx b/tools/qa/cppunit/test_pathutils.cxx
index 7ad75f1e8db2..a7a065c34761 100644
--- a/tools/qa/cppunit/test_pathutils.cxx
+++ b/tools/qa/cppunit/test_pathutils.cxx
@@ -26,13 +26,11 @@
namespace
{
-void buildPath(wchar_t const* front, wchar_t const* back, wchar_t const* path)
+void buildPath(std::wstring_view front, std::wstring_view back, wchar_t const* path)
{
#if defined(_WIN32)
- wchar_t p[MAX_PATH];
- wchar_t* e = tools::buildPath(p, front, front + std::wcslen(front), back, std::wcslen(back));
- CPPUNIT_ASSERT_EQUAL(static_cast<void*>(p + std::wcslen(path)), static_cast<void*>(e));
- CPPUNIT_ASSERT_EQUAL(0, std::wcscmp(path, p));
+ std::wstring s = tools::buildPath(front, back);
+ CPPUNIT_ASSERT_EQUAL(0, std::wcscmp(path, s.c_str()));
#else
(void)front;
(void)back;
diff --git a/tools/source/misc/pathutils.cxx b/tools/source/misc/pathutils.cxx
index 706740a320f9..30bdbde8f013 100644
--- a/tools/source/misc/pathutils.cxx
+++ b/tools/source/misc/pathutils.cxx
@@ -43,63 +43,40 @@ WCHAR * filename(WCHAR * path) {
}
}
-WCHAR * buildPath(
- WCHAR * path, WCHAR const * frontBegin, WCHAR const * frontEnd,
- WCHAR const * backBegin, std::size_t backLength)
+std::wstring buildPath(std::wstring_view front, std::wstring_view back)
{
// Remove leading ".." segments in the second path together with matching
// segments in the first path that are neither empty nor "." nor ".." nor
// end in ":" (which is not foolproof, as it can erroneously erase the start
// of a UNC path, but only if the input is bad data):
- while (backLength >= 2 && backBegin[0] == L'.' && backBegin[1] == L'.' &&
- (backLength == 2 || backBegin[2] == L'\\'))
+ while (back.starts_with(L"..") &&
+ (back.size() == 2 || back[2] == L'\\'))
{
- if (frontEnd - frontBegin < 2 || frontEnd[-1] != L'\\' ||
- frontEnd[-2] == L'\\' || frontEnd[-2] == L':' ||
- (frontEnd[-2] == L'.' &&
- (frontEnd - frontBegin < 3 || frontEnd[-3] == L'\\' ||
- (frontEnd[-3] == L'.' &&
- (frontEnd - frontBegin < 4 || frontEnd[-4] == L'\\')))))
+ if (front.size() < 2 || front.back() != L'\\' ||
+ front[front.size() - 2] == L'\\' || front[front.size() - 2] == L':' ||
+ (front[front.size() - 2] == L'.' &&
+ (front.size() < 3 || front[front.size() - 3] == L'\\' ||
+ (front[front.size() - 3] == L'.' &&
+ (front.size() < 4 || front[front.size() - 4] == L'\\')))))
{
break;
}
- WCHAR const * p = frontEnd - 1;
- while (p != frontBegin && p[-1] != L'\\') {
+ auto p = front.end() - 1;
+ while (p != front.begin() && p[-1] != L'\\') {
--p;
}
- if (p == frontBegin) {
+ if (p == front.begin()) {
break;
}
- frontEnd = p;
- if (backLength == 2) {
- backBegin += 2;
- backLength -= 2;
+ front.remove_suffix(front.end() - p);
+ if (back.size() == 2) {
+ back = {};
} else {
- backBegin += 3;
- backLength -= 3;
+ back.remove_prefix(3);
}
}
- if (backLength <
- o3tl::make_unsigned(MAX_PATH - (frontEnd - frontBegin)))
- {
- WCHAR * p;
- if (frontBegin == path) {
- p = const_cast< WCHAR * >(frontEnd);
- } else {
- p = path;
- while (frontBegin != frontEnd) {
- *p++ = *frontBegin++;
- }
- }
- for (; backLength > 0; --backLength) {
- *p++ = *backBegin++;
- }
- *p = L'\0';
- return p;
- } else {
- SetLastError(ERROR_FILENAME_EXCED_RANGE);
- return nullptr;
- }
+
+ return std::wstring(front) + std::wstring(back);
}
}