Fix unintentional locale dependency (#3358)
Avoid unintentional locale dependency hb_variation_to_string uses sprintf with %g, which will produce a locale-dependent decimal point, which is not desired here. The output is supposed to be compatible with CSS syntax, and that always uses '.' for the decimal point. Fix this by changing the per-thread locale to "C" around sprintf call. Fixes https://github.com/harfbuzz/harfbuzz/issues/3355 Fixes https://github.com/harfbuzz/harfbuzz/pull/3357 Fixes https://github.com/harfbuzz/harfbuzz/pull/3358 Co-authored-by: Matthias Clasen <mclasen@redhat.com>
This commit is contained in:
parent
d70825a6d1
commit
a45a630539
|
@ -68,8 +68,8 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
|
|||
])
|
||||
|
||||
# Functions and headers
|
||||
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty)
|
||||
AC_CHECK_HEADERS(unistd.h sys/mman.h stdbool.h)
|
||||
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale uselocale)
|
||||
AC_CHECK_HEADERS(unistd.h sys/mman.h stdbool.h xlocale.h)
|
||||
|
||||
# Compiler flags
|
||||
AC_CANONICAL_HOST
|
||||
|
|
|
@ -61,6 +61,7 @@ check_headers = [
|
|||
['unistd.h'],
|
||||
['sys/mman.h'],
|
||||
['stdbool.h'],
|
||||
['xlocale.h'],
|
||||
]
|
||||
|
||||
check_funcs = [
|
||||
|
@ -70,6 +71,8 @@ check_funcs = [
|
|||
['getpagesize'],
|
||||
['mmap'],
|
||||
['isatty'],
|
||||
['uselocale'],
|
||||
['newlocale'],
|
||||
]
|
||||
|
||||
m_dep = cpp.find_library('m', required: false)
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
|
||||
#include <locale.h>
|
||||
|
||||
#ifdef HAVE_XLOCALE_H
|
||||
#include <xlocale.h> // Needed on BSD/OS X for uselocale
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_SETLOCALE
|
||||
#define setlocale(Category, Locale) "C"
|
||||
#endif
|
||||
|
@ -1039,6 +1043,56 @@ hb_variation_from_string (const char *str, int len,
|
|||
return false;
|
||||
}
|
||||
|
||||
#if !defined(HARFBUZZ_NO_SETLOCALE) && defined(HAVE_NEWLOCALE) && defined(HAVE_USELOCALE)
|
||||
|
||||
#ifdef WIN32
|
||||
using locale_t = _locale_t;
|
||||
#endif
|
||||
|
||||
static inline void free_static_C_locale ();
|
||||
|
||||
static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<locale_t>,
|
||||
hb_C_locale_lazy_loader_t>
|
||||
{
|
||||
static locale_t create ()
|
||||
{
|
||||
locale_t l = newlocale (LC_ALL_MASK, "C", NULL);
|
||||
if (!l)
|
||||
return l;
|
||||
|
||||
hb_atexit (free_static_C_locale);
|
||||
|
||||
return l;
|
||||
}
|
||||
static void destroy (locale_t l)
|
||||
{
|
||||
freelocale (l);
|
||||
}
|
||||
static locale_t get_null ()
|
||||
{
|
||||
return (locale_t) 0;
|
||||
}
|
||||
} static_C_locale;
|
||||
|
||||
static inline
|
||||
void free_static_C_locale ()
|
||||
{
|
||||
static_C_locale.free_instance ();
|
||||
}
|
||||
|
||||
static locale_t
|
||||
get_C_locale ()
|
||||
{
|
||||
return static_C_locale.get_unconst ();
|
||||
}
|
||||
|
||||
#else
|
||||
#ifdef WIN32
|
||||
#define locale_t void *
|
||||
#endif
|
||||
#define uselocale(Locale) ((locale_t) 0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_variation_to_string:
|
||||
* @variation: an #hb_variation_t to convert
|
||||
|
@ -1064,7 +1118,11 @@ hb_variation_to_string (hb_variation_t *variation,
|
|||
while (len && s[len - 1] == ' ')
|
||||
len--;
|
||||
s[len++] = '=';
|
||||
|
||||
locale_t oldlocale HB_UNUSED;
|
||||
oldlocale = uselocale (get_C_locale ());
|
||||
len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
|
||||
(void) uselocale (oldlocale);
|
||||
|
||||
assert (len < ARRAY_LENGTH (s));
|
||||
len = hb_min (len, size - 1);
|
||||
|
|
Loading…
Reference in New Issue