summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorAmalthea Skydancer <amalthea@faen.dev>2026-02-22 01:49:53 +0100
committerAndrey Lihatskiy <118752495+marchcat@users.noreply.github.com>2026-03-18 06:39:29 +0200
commitd045f9aa32789a35628aced166145c182751acbf (patch)
tree79691fa42e15b7c0d41f8a73f8543b5d0f1ee9fd /indra
parentb82720f9d60302cb15d0e260860143e4b2c14b92 (diff)
Fix locale thousands separator producing '?' on Linux with multibyte UTF-8 separators
getThousandsSeparator() and getMonetaryThousandsSeparator() extracted only the first byte of localeconv()->thousands_sep, truncating multibyte UTF-8 separator characters (e.g. non-breaking space U+00A0). The incomplete byte was then embedded via %c format specifier, producing invalid UTF-8 rendered as '?' in notifications like avatar complexity. Return the full separator string and use string concatenation instead of %c.
Diffstat (limited to 'indra')
-rw-r--r--indra/llui/llresmgr.cpp40
-rw-r--r--indra/llui/llresmgr.h4
2 files changed, 14 insertions, 30 deletions
diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp
index 111c732548..f00d876b2b 100644
--- a/indra/llui/llresmgr.cpp
+++ b/indra/llui/llresmgr.cpp
@@ -54,11 +54,9 @@ char LLResMgr::getDecimalPoint() const
return decimal;
}
-char LLResMgr::getThousandsSeparator() const
+std::string LLResMgr::getThousandsSeparator() const
{
- char separator = localeconv()->thousands_sep[0];
-
- return separator;
+ return localeconv()->thousands_sep;
}
char LLResMgr::getMonetaryDecimalPoint() const
@@ -68,11 +66,9 @@ char LLResMgr::getMonetaryDecimalPoint() const
return decimal;
}
-char LLResMgr::getMonetaryThousandsSeparator() const
+std::string LLResMgr::getMonetaryThousandsSeparator() const
{
- char separator = localeconv()->mon_thousands_sep[0];
-
- return separator;
+ return localeconv()->mon_thousands_sep;
}
@@ -85,7 +81,7 @@ std::string LLResMgr::getMonetaryString( S32 input ) const
struct lconv *conv = localeconv();
char* negative_sign = conv->negative_sign;
- char separator = getMonetaryThousandsSeparator();
+ std::string separator = getMonetaryThousandsSeparator();
char* grouping = conv->mon_grouping;
// Note on mon_grouping:
@@ -135,10 +131,7 @@ std::string LLResMgr::getMonetaryString( S32 input ) const
}
S32 group_count = cur_group;
- char reversed_output[20] = ""; /* Flawfinder: ignore */
- char forward_output[20] = ""; /* Flawfinder: ignore */
- S32 output_pos = 0;
-
+ std::string formatted;
cur_group = 0;
S32 pos = static_cast<S32>(digits.size()) - 1;
S32 count_within_group = 0;
@@ -148,7 +141,7 @@ std::string LLResMgr::getMonetaryString( S32 input ) const
if( count_within_group > groupings[cur_group] )
{
count_within_group = 1;
- reversed_output[ output_pos++ ] = separator;
+ formatted = separator + formatted;
if( (cur_group + 1) >= group_count )
{
@@ -160,28 +153,19 @@ std::string LLResMgr::getMonetaryString( S32 input ) const
cur_group++;
}
}
- reversed_output[ output_pos++ ] = digits[pos--];
+ formatted = std::string(1, digits[pos--]) + formatted;
}
while( pos >= 0 )
{
- reversed_output[ output_pos++ ] = digits[pos--];
- }
-
-
- reversed_output[ output_pos ] = '\0';
- forward_output[ output_pos ] = '\0';
-
- for( S32 i = 0; i < output_pos; i++ )
- {
- forward_output[ output_pos - 1 - i ] = reversed_output[ i ];
+ formatted = std::string(1, digits[pos--]) + formatted;
}
if( negative_before )
{
output.append( negative_sign );
}
- output.append( forward_output );
+ output.append( formatted );
if( negative_after )
{
output.append( negative_sign );
@@ -210,11 +194,11 @@ void LLResMgr::getIntegerString( std::string& output, S32 input ) const
{
if (fraction == remaining_count)
{
- fraction_string = llformat_to_utf8("%d%c", fraction, getThousandsSeparator());
+ fraction_string = llformat_to_utf8("%d", fraction) + getThousandsSeparator();
}
else
{
- fraction_string = llformat_to_utf8("%3.3d%c", fraction, getThousandsSeparator());
+ fraction_string = llformat_to_utf8("%3.3d", fraction) + getThousandsSeparator();
}
output = fraction_string + output;
}
diff --git a/indra/llui/llresmgr.h b/indra/llui/llresmgr.h
index 7ad6659a44..8ceb584ec5 100644
--- a/indra/llui/llresmgr.h
+++ b/indra/llui/llresmgr.h
@@ -49,10 +49,10 @@ public:
LLLOCALE_ID getLocale() const { return mLocale; }
char getDecimalPoint() const;
- char getThousandsSeparator() const;
+ std::string getThousandsSeparator() const;
char getMonetaryDecimalPoint() const;
- char getMonetaryThousandsSeparator() const;
+ std::string getMonetaryThousandsSeparator() const;
std::string getMonetaryString( S32 input ) const;
void getIntegerString( std::string& output, S32 input ) const;