From ed56301abd8ba11463b340b4c5c6f7af57ed6623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Wojni=C5=82owicz?= Date: Sat, 16 May 2020 12:53:50 +0200 Subject: [PATCH] ICU-20545 Ensure that path ends with detected file separator CharString, when asked, appends U_FILE_SEP_CHAR at the end of the string it holds, if it won't find U_FILE_SEP_CHAR or U_FILE_ALT_SEP_CHAR there. The problem starts if the dir variable uses U_FILE_ALT_SEP_CHAR which is not equal to U_FILE_SEP_CHAR. Then the resulting path could look like this ../data\ instead of this ../data/ This patch uses U_FILE_SEP_CHAR unless it detects that the dir variable doesn't use it, and uses U_FILE_ALT_SEP_CHAR instead. --- icu4c/source/common/charstr.cpp | 14 ++++++++++++-- icu4c/source/common/charstr.h | 10 ++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/icu4c/source/common/charstr.cpp b/icu4c/source/common/charstr.cpp index dda29dac632..4878c737fb5 100644 --- a/icu4c/source/common/charstr.cpp +++ b/icu4c/source/common/charstr.cpp @@ -197,7 +197,7 @@ CharString &CharString::appendPathPart(StringPiece s, UErrorCode &errorCode) { } char c; if(len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) { - append(U_FILE_SEP_CHAR, errorCode); + append(getDirSepChar(), errorCode); } append(s, errorCode); return *this; @@ -207,9 +207,19 @@ CharString &CharString::ensureEndsWithFileSeparator(UErrorCode &errorCode) { char c; if(U_SUCCESS(errorCode) && len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) { - append(U_FILE_SEP_CHAR, errorCode); + append(getDirSepChar(), errorCode); } return *this; } +char CharString::getDirSepChar() const { + char dirSepChar = U_FILE_SEP_CHAR; +#if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR) + // We may need to return a different directory separator when building for Cygwin or MSYS2. + if(len>0 && !uprv_strchr(data(), U_FILE_SEP_CHAR) && uprv_strchr(data(), U_FILE_ALT_SEP_CHAR)) + dirSepChar = U_FILE_ALT_SEP_CHAR; +#endif + return dirSepChar; +} + U_NAMESPACE_END diff --git a/icu4c/source/common/charstr.h b/icu4c/source/common/charstr.h index 23b950ed6ec..9400fbb5461 100644 --- a/icu4c/source/common/charstr.h +++ b/icu4c/source/common/charstr.h @@ -141,13 +141,13 @@ public: /** * Appends a filename/path part, e.g., a directory name. - * First appends a U_FILE_SEP_CHAR if necessary. + * First appends a U_FILE_SEP_CHAR or U_FILE_ALT_SEP_CHAR if necessary. * Does nothing if s is empty. */ CharString &appendPathPart(StringPiece s, UErrorCode &errorCode); /** - * Appends a U_FILE_SEP_CHAR if this string is not empty + * Appends a U_FILE_SEP_CHAR or U_FILE_ALT_SEP_CHAR if this string is not empty * and does not already end with a U_FILE_SEP_CHAR or U_FILE_ALT_SEP_CHAR. */ CharString &ensureEndsWithFileSeparator(UErrorCode &errorCode); @@ -160,6 +160,12 @@ private: CharString(const CharString &other); // forbid copying of this class CharString &operator=(const CharString &other); // forbid copying of this class + + /** + * Returns U_FILE_ALT_SEP_CHAR if found in string, and U_FILE_SEP_CHAR is not found. + * Otherwise returns U_FILE_SEP_CHAR. + */ + char getDirSepChar() const; }; U_NAMESPACE_END