On Sat, Mar 28, 2015 at 12:51 PM, Nikos Mavrogiannopoulos <n...@gnutls.org> wrote: > Hello Simon, > Robert reported some invalid memory access in gnutls, and one I traced > it back to libidn. A reproducer is attached. The reproducer uses strings > on the heap because valgrind doesn't seem to detect such accesses on the > stack. > ==623== Invalid read of size 1 > ==623== at 0x4E38E7F: g_utf8_to_ucs4_fast (nfkc.c:399) > ==623== by 0x4E38E7F: stringprep_utf8_to_ucs4 (nfkc.c:1023) > ==623== by 0x4E3A7DE: idna_to_ascii_8z (idna.c:578) > ==623== by 0x4005FD: main (in /home/nmav/cvs/gnutls/lib/a.out) > ==623== Address 0x541105f is 1 bytes after a block of size 30 alloc'd > ==623== at 0x4C28C20: malloc (vg_replace_malloc.c:296) > ==623== by 0x50E99D9: strdup (strdup.c:42) > ==623== by 0x4005E0: main (in /home/nmav/cvs/gnutls/lib/a.out)
The attached patches handle the reported issue. However, all functions which use g_utf8_next_char() including g_utf8_strlen() are affected. regards, Nikos
From 1eb41ae34b462dda54abec756234651a2e1bc0e1 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos <n...@gnutls.org> Date: Sat, 28 Mar 2015 13:24:23 +0100 Subject: [PATCH 1/2] g_utf8_to_ucs4_fast: prevent access past the end of string --- lib/nfkc.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/nfkc.c b/lib/nfkc.c index fbea0c8..b5679de 100644 --- a/lib/nfkc.c +++ b/lib/nfkc.c @@ -389,25 +389,36 @@ g_utf8_to_ucs4_fast (const gchar * str, glong len, glong * items_written) gunichar *result; gsize n_chars, i; const gchar *p; + glong left = len, skip; g_return_val_if_fail (str != NULL, NULL); + /* left holds the length in bytes */ + if (left < 0) left = strlen(str); + p = str; n_chars = 0; if (len < 0) { while (*p) { - p = g_utf8_next_char (p); + skip = g_utf8_skip[*(const guchar *)(p)]; + left -= skip; + p += skip; ++n_chars; + if (left < 0) + return NULL; } } else { while (p < str + len && *p) { - p = g_utf8_next_char (p); + skip = g_utf8_skip[*(const guchar *)(p)]; + p += skip; ++n_chars; + if (left < 0) + return NULL; } } -- 2.1.4
From 02f3d1f52b8c279f826ccda2d2cccb6ff7ec65cb Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos <n...@gnutls.org> Date: Sat, 28 Mar 2015 13:27:47 +0100 Subject: [PATCH 2/2] Added a check for invalid encodings --- tests/Makefile.am | 2 +- tests/tst_invalid.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/tst_invalid.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 0f491ec..acb50b3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -27,7 +27,7 @@ libutils_a_SOURCES = utils.h utils.c ctests = tst_stringprep tst_punycode tst_idna tst_idna2 tst_idna3 \ tst_idna4 tst_nfkc tst_pr29 tst_strerror tst_toutf8 \ - tst_symbols + tst_symbols tst_invalid if TLD ctests += tst_tld endif diff --git a/tests/tst_invalid.c b/tests/tst_invalid.c new file mode 100644 index 0000000..32285a5 --- /dev/null +++ b/tests/tst_invalid.c @@ -0,0 +1,52 @@ +/* tst_idna.c --- Self tests for idna_to_ascii(). + * Copyright (C) 2015 Nikos Mavrogiannopoulos + * + * This file is part of GNU Libidn. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +#include <stdlib.h> +#include <string.h> +#include <idna.h> + +int main() +{ + char *s = NULL, *s2 = NULL; + int rc; + char *x1 = strdup("\x7e\x64\x61\x72\x10\x2f\x2f\xf9\x2b\x71\x60\x79\x7b\x2e\x63\x75\x2b\x61\x65\x72\x75\x65\x56\x66\x7f\x62\xc5\x76\xe5\x00"); + char *x2 = strdup("\x76\x72\x6f\x63\x65\x72\x74\x2e\x79\x65\x5e\xdc\xf6\xd0\x00"); + + + rc = idna_to_ascii_8z(x1, &s, 0); + if (rc == IDNA_SUCCESS) { + /* should have failed */ + exit(1); + } + + rc = idna_to_ascii_8z(x2, &s2, 0); + if (rc == IDNA_SUCCESS) { + /* should have failed */ + exit(1); + } + free(x1); + free(x2); + exit(0); +} -- 2.1.4
_______________________________________________ Help-libidn mailing list Help-libidn@gnu.org https://lists.gnu.org/mailman/listinfo/help-libidn