summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2021-03-15 21:23:43 +0100
committerAndy Wingo <wingo@pobox.com>2021-03-15 21:23:43 +0100
commitd87b57a00bb8f755fdca46d10c9d411d48efa1e9 (patch)
tree81c0c690ae5c4a766839abaa1c50b2e768e47778
parent5a1a1eee5061f6b7deda7d187123561f8f7e5aae (diff)
downloadguile-d87b57a00bb8f755fdca46d10c9d411d48efa1e9.tar.gz
Fix buffer overread in string-locale-ci=? and related functions
* libguile/i18n.c (u32_locale_casecoll): Take lengths of incoming strings as parameters rather than assuming "nul" termination. (compare_u32_strings_ci): Pass string lengths as computed from the Scheme strings. * test-suite/tests/i18n.test ("text collation (English)"): Add a test case. Thanks a million to Rob Browning for the report.
-rw-r--r--libguile/i18n.c20
-rw-r--r--test-suite/tests/i18n.test10
2 files changed, 18 insertions, 12 deletions
diff --git a/libguile/i18n.c b/libguile/i18n.c
index fc47fdfe5..cc4ef7370 100644
--- a/libguile/i18n.c
+++ b/libguile/i18n.c
@@ -833,9 +833,8 @@ locale_language ()
}
static inline int
-u32_locale_casecoll (const char *func_name, const uint32_t *c_s1,
- const uint32_t *c_s2,
- int *result)
+u32_locale_casecoll (const char *func_name, const uint32_t *c_s1, size_t s1_len,
+ const uint32_t *c_s2, size_t s2_len, int *result)
{
/* Note: Since this is called from `RUN_IN_LOCALE_SECTION', it must note
make any non-local exit. */
@@ -843,8 +842,8 @@ u32_locale_casecoll (const char *func_name, const uint32_t *c_s1,
int ret;
const char *loc = locale_language ();
- ret = u32_casecoll (c_s1, u32_strlen (c_s1),
- c_s2, u32_strlen (c_s2),
+ ret = u32_casecoll (c_s1, s1_len,
+ c_s2, s2_len,
loc, UNINORM_NFC, result);
return ret == 0 ? ret : errno;
@@ -860,6 +859,9 @@ compare_u32_strings_ci (SCM s1, SCM s2, SCM locale, const char *func_name)
int c_s1_malloc_p, c_s2_malloc_p;
SCM_VALIDATE_OPTIONAL_LOCALE_COPY (3, locale, c_locale);
+ size_t s1_len = scm_i_string_length (s1);
+ size_t s2_len = scm_i_string_length (s2);
+
SCM_STRING_TO_U32_BUF (s1, c_s1, c_s1_malloc_p);
SCM_STRING_TO_U32_BUF (s2, c_s2, c_s2_malloc_p);
@@ -867,13 +869,13 @@ compare_u32_strings_ci (SCM s1, SCM s2, SCM locale, const char *func_name)
RUN_IN_LOCALE_SECTION
(c_locale,
ret = u32_locale_casecoll (func_name,
- (const uint32_t *) c_s1,
- (const uint32_t *) c_s2,
+ (const uint32_t *) c_s1, s1_len,
+ (const uint32_t *) c_s2, s2_len,
&result));
else
ret = u32_locale_casecoll (func_name,
- (const uint32_t *) c_s1,
- (const uint32_t *) c_s2,
+ (const uint32_t *) c_s1, s1_len,
+ (const uint32_t *) c_s2, s2_len,
&result);
SCM_CLEANUP_U32_BUF(c_s1, c_s1_malloc_p);
diff --git a/test-suite/tests/i18n.test b/test-suite/tests/i18n.test
index 427aef4f5..f288da06d 100644
--- a/test-suite/tests/i18n.test
+++ b/test-suite/tests/i18n.test
@@ -1,8 +1,7 @@
;;;; i18n.test --- Exercise the i18n API. -*- coding: utf-8; mode: scheme; -*-
;;;;
-;;;; Copyright (C) 2006, 2007, 2009, 2010, 2011, 2012,
-;;;; 2013, 2014, 2015, 2016, 2017, 2018 Free Software Foundation, Inc.
-;;;; Ludovic Courtès
+;;;; Copyright (C) 2006-2007,2009-2019,2021 Free Software Foundation, Inc.
+;;;; Author: Ludovic Courtès
;;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
@@ -75,6 +74,11 @@
(string-locale-ci=? "Hello" "HELLO"
(make-locale (list LC_COLLATE) "C"))))
+ (pass-if "string-locale-ci=?, bis"
+ (let* ((strings (list "⇒a" "⇒b"))
+ (heads (map (lambda (s) (substring/shared s 0 1)) strings)))
+ (apply string-locale-ci=? heads)))
+
(pass-if "string-locale-ci<?"
(and (string-locale-ci<? "hello" "WORLD")
(string-locale-ci<? "hello" "WORLD"