summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2021-03-15 22:02:12 +0100
committerAndy Wingo <wingo@pobox.com>2021-03-15 22:02:12 +0100
commit72bf9d93ca63d8866cd7f4167469c2d5a5c91c2b (patch)
tree0be9f5fb12280f8bcef7c54ef66e553d7d1d57b1
parent8a8727db5cffb10883a837eea3b7737abdd58188 (diff)
downloadguile-72bf9d93ca63d8866cd7f4167469c2d5a5c91c2b.tar.gz
Fix buffer overread in string-locale<?
* libguile/i18n.c (compare_strings): In all cases, convert to a null-terminated string. While we're doing that, might as well use utf-8. * test-suite/tests/i18n.test ("text collation (French)"): Add test. Thanks again to Rob Browning for the report.
-rw-r--r--libguile/i18n.c41
-rw-r--r--test-suite/tests/i18n.test7
2 files changed, 25 insertions, 23 deletions
diff --git a/libguile/i18n.c b/libguile/i18n.c
index cc4ef7370..52a808041 100644
--- a/libguile/i18n.c
+++ b/libguile/i18n.c
@@ -788,34 +788,29 @@ SCM_DEFINE (scm_locale_p, "locale?", 1, 0, 0,
} while (0)
-/* Compare UTF-32 strings according to LOCALE. Returns a negative value if
- S1 compares smaller than S2, a positive value if S1 compares larger than
+/* Compare strings according to LOCALE. Returns a negative value if S1
+ compares smaller than S2, a positive value if S1 compares larger than
S2, or 0 if they compare equal. */
static inline int
-compare_u32_strings (SCM s1, SCM s2, SCM locale, const char *func_name)
+compare_strings (SCM s1, SCM s2, SCM locale, const char *func_name)
#define FUNC_NAME func_name
{
int result;
scm_t_locale c_locale;
- scm_t_wchar *c_s1, *c_s2;
- int c_s1_malloc_p, c_s2_malloc_p;
+ uint8_t *c_s1, *c_s2;
SCM_VALIDATE_OPTIONAL_LOCALE_COPY (3, locale, c_locale);
- SCM_STRING_TO_U32_BUF (s1, c_s1, c_s1_malloc_p);
- SCM_STRING_TO_U32_BUF (s2, c_s2, c_s2_malloc_p);
+ c_s1 = (uint8_t *) scm_to_utf8_string (s1);
+ c_s2 = (uint8_t *) scm_to_utf8_string (s2);
if (c_locale)
- RUN_IN_LOCALE_SECTION (c_locale,
- result = u32_strcoll ((const uint32_t *) c_s1,
- (const uint32_t *) c_s2));
+ RUN_IN_LOCALE_SECTION (c_locale, result = u8_strcoll (c_s1, c_s2));
else
- result = u32_strcoll ((const uint32_t *) c_s1,
- (const uint32_t *) c_s2);
+ result = u8_strcoll (c_s1, c_s2);
- SCM_CLEANUP_U32_BUF(c_s1, c_s1_malloc_p);
- SCM_CLEANUP_U32_BUF(c_s2, c_s2_malloc_p);
+ free (c_s1);
+ free (c_s2);
- scm_remember_upto_here_2 (s1, s2);
scm_remember_upto_here (locale);
return result;
}
@@ -907,7 +902,7 @@ SCM_DEFINE (scm_string_locale_lt, "string-locale<?", 2, 1, 0,
SCM_VALIDATE_STRING (1, s1);
SCM_VALIDATE_STRING (2, s2);
- result = compare_u32_strings (s1, s2, locale, FUNC_NAME);
+ result = compare_strings (s1, s2, locale, FUNC_NAME);
return scm_from_bool (result < 0);
}
@@ -926,7 +921,7 @@ SCM_DEFINE (scm_string_locale_gt, "string-locale>?", 2, 1, 0,
SCM_VALIDATE_STRING (1, s1);
SCM_VALIDATE_STRING (2, s2);
- result = compare_u32_strings (s1, s2, locale, FUNC_NAME);
+ result = compare_strings (s1, s2, locale, FUNC_NAME);
return scm_from_bool (result > 0);
}
@@ -1004,9 +999,9 @@ SCM_DEFINE (scm_char_locale_lt, "char-locale<?", 2, 1, 0,
SCM_VALIDATE_CHAR (1, c1);
SCM_VALIDATE_CHAR (2, c2);
- result = compare_u32_strings (scm_string (scm_list_1 (c1)),
- scm_string (scm_list_1 (c2)),
- locale, FUNC_NAME);
+ result = compare_strings (scm_string (scm_list_1 (c1)),
+ scm_string (scm_list_1 (c2)),
+ locale, FUNC_NAME);
return scm_from_bool (result < 0);
}
@@ -1023,9 +1018,9 @@ SCM_DEFINE (scm_char_locale_gt, "char-locale>?", 2, 1, 0,
SCM_VALIDATE_CHAR (1, c1);
SCM_VALIDATE_CHAR (2, c2);
- result = compare_u32_strings (scm_string (scm_list_1 (c1)),
- scm_string (scm_list_1 (c2)),
- locale, FUNC_NAME);
+ result = compare_strings (scm_string (scm_list_1 (c1)),
+ scm_string (scm_list_1 (c2)),
+ locale, FUNC_NAME);
return scm_from_bool (result > 0);
}
diff --git a/test-suite/tests/i18n.test b/test-suite/tests/i18n.test
index 6abd00fee..a19b96336 100644
--- a/test-suite/tests/i18n.test
+++ b/test-suite/tests/i18n.test
@@ -221,6 +221,13 @@
(lambda ()
(setlocale LC_ALL "C"))))))
+ (pass-if "string-locale<?, bis"
+ (under-french-utf8-locale-or-unresolved
+ (lambda ()
+ (let* ((strings (list "œa" "œb"))
+ (heads (map (lambda (s) (substring/shared s 0 1)) strings)))
+ (not (apply string-locale<? heads))))))
+
(pass-if "string-locale-ci=?, bis"
(under-french-utf8-locale-or-unresolved
(lambda ()