You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
5.2 KiB
182 lines
5.2 KiB
From e4613df21e25e063d120ee23a650c65cd16df4be Mon Sep 17 00:00:00 2001 |
|
From: Stefan Liebler <stli@linux.vnet.ibm.com> |
|
Date: Mon, 7 Nov 2016 17:30:22 +0100 |
|
Subject: [PATCH 16/17] Fix ucs4le_internal_loop in error case. [BZ #19726] |
|
|
|
Upstream commit 8f25676c83eef5c85db98f9cf027890fbe810447 |
|
|
|
When converting from UCS4LE to INTERNAL, the input-value is checked for a too |
|
large value and the iconv() call sets errno to EILSEQ. In this case the inbuf |
|
argument of the iconv() call should point to the invalid character, but it |
|
points to the beginning of the inbuf. |
|
Thus this patch updates the pointers inptrp and outptrp before returning in |
|
this error case. |
|
|
|
This patch also adds a new testcase for this issue. |
|
The new test was tested on a s390, power, intel machine. |
|
|
|
ChangeLog: |
|
|
|
[BZ #19726] |
|
* iconv/gconv_simple.c (ucs4le_internal_loop): Update inptrp and |
|
outptrp in case of an illegal input. |
|
* iconv/tst-iconv6.c: New file. |
|
* iconv/Makefile (tests): Add tst-iconv6. |
|
--- |
|
iconv/Makefile | 2 +- |
|
iconv/gconv_simple.c | 2 + |
|
iconv/tst-iconv6.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
3 files changed, 120 insertions(+), 1 deletion(-) |
|
create mode 100644 iconv/tst-iconv6.c |
|
|
|
diff --git a/iconv/Makefile b/iconv/Makefile |
|
index 3e7f567..4d34c3f 100644 |
|
--- a/iconv/Makefile |
|
+++ b/iconv/Makefile |
|
@@ -43,7 +43,7 @@ CFLAGS-charmap.c = -DCHARMAP_PATH='"$(i18ndir)/charmaps"' \ |
|
CFLAGS-linereader.c = -DNO_TRANSLITERATION |
|
CFLAGS-simple-hash.c = -I../locale |
|
|
|
-tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 |
|
+tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 |
|
|
|
others = iconv_prog iconvconfig |
|
install-others-programs = $(inst_bindir)/iconv |
|
diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c |
|
index 8697309..b9f846d 100644 |
|
--- a/iconv/gconv_simple.c |
|
+++ b/iconv/gconv_simple.c |
|
@@ -634,6 +634,8 @@ ucs4le_internal_loop (struct __gconv_step *step, |
|
continue; |
|
} |
|
|
|
+ *inptrp = inptr; |
|
+ *outptrp = outptr; |
|
return __GCONV_ILLEGAL_INPUT; |
|
} |
|
|
|
diff --git a/iconv/tst-iconv6.c b/iconv/tst-iconv6.c |
|
new file mode 100644 |
|
index 0000000..57d7f38 |
|
--- /dev/null |
|
+++ b/iconv/tst-iconv6.c |
|
@@ -0,0 +1,117 @@ |
|
+/* Testing ucs4le_internal_loop() in gconv_simple.c. |
|
+ Copyright (C) 2016 Free Software Foundation, Inc. |
|
+ This file is part of the GNU C Library. |
|
+ |
|
+ The GNU C Library is free software; you can redistribute it and/or |
|
+ modify it under the terms of the GNU Lesser General Public |
|
+ License as published by the Free Software Foundation; either |
|
+ version 2.1 of the License, or (at your option) any later version. |
|
+ |
|
+ The GNU C Library 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 |
|
+ Lesser General Public License for more details. |
|
+ |
|
+ You should have received a copy of the GNU Lesser General Public |
|
+ License along with the GNU C Library; if not, see |
|
+ <http://www.gnu.org/licenses/>. */ |
|
+ |
|
+#include <stdio.h> |
|
+#include <errno.h> |
|
+#include <string.h> |
|
+#include <inttypes.h> |
|
+#include <iconv.h> |
|
+#include <byteswap.h> |
|
+ |
|
+static int |
|
+do_test (void) |
|
+{ |
|
+ iconv_t cd; |
|
+ char *inptr; |
|
+ size_t inlen; |
|
+ char *outptr; |
|
+ size_t outlen; |
|
+ size_t n; |
|
+ int e; |
|
+ int result = 0; |
|
+ |
|
+#if __BYTE_ORDER == __BIG_ENDIAN |
|
+ /* On big-endian machines, ucs4le_internal_loop() swaps the bytes before |
|
+ error checking. Thus the input values has to be swapped. */ |
|
+# define VALUE(val) bswap_32 (val) |
|
+#else |
|
+# define VALUE(val) val |
|
+#endif |
|
+ uint32_t inbuf[3] = { VALUE (0x41), VALUE (0x80000000), VALUE (0x42) }; |
|
+ uint32_t outbuf[3] = { 0, 0, 0 }; |
|
+ |
|
+ cd = iconv_open ("WCHAR_T", "UCS-4LE"); |
|
+ if (cd == (iconv_t) -1) |
|
+ { |
|
+ printf ("cannot convert from UCS4LE to wchar_t: %m\n"); |
|
+ return 1; |
|
+ } |
|
+ |
|
+ inptr = (char *) inbuf; |
|
+ inlen = sizeof (inbuf); |
|
+ outptr = (char *) outbuf; |
|
+ outlen = sizeof (outbuf); |
|
+ |
|
+ n = iconv (cd, &inptr, &inlen, &outptr, &outlen); |
|
+ e = errno; |
|
+ |
|
+ if (n != (size_t) -1) |
|
+ { |
|
+ printf ("incorrect iconv() return value: %zd, expected -1\n", n); |
|
+ result = 1; |
|
+ } |
|
+ |
|
+ if (e != EILSEQ) |
|
+ { |
|
+ printf ("incorrect error value: %s, expected %s\n", |
|
+ strerror (e), strerror (EILSEQ)); |
|
+ result = 1; |
|
+ } |
|
+ |
|
+ if (inptr != (char *) &inbuf[1]) |
|
+ { |
|
+ printf ("inptr=0x%p does not point to invalid character! Expected=0x%p\n" |
|
+ , inptr, &inbuf[1]); |
|
+ result = 1; |
|
+ } |
|
+ |
|
+ if (inlen != sizeof (inbuf) - sizeof (uint32_t)) |
|
+ { |
|
+ printf ("inlen=%zd != %zd\n" |
|
+ , inlen, sizeof (inbuf) - sizeof (uint32_t)); |
|
+ result = 1; |
|
+ } |
|
+ |
|
+ if (outptr != (char *) &outbuf[1]) |
|
+ { |
|
+ printf ("outptr=0x%p does not point to invalid character in inbuf! " |
|
+ "Expected=0x%p\n" |
|
+ , outptr, &outbuf[1]); |
|
+ result = 1; |
|
+ } |
|
+ |
|
+ if (outlen != sizeof (inbuf) - sizeof (uint32_t)) |
|
+ { |
|
+ printf ("outlen=%zd != %zd\n" |
|
+ , outlen, sizeof (outbuf) - sizeof (uint32_t)); |
|
+ result = 1; |
|
+ } |
|
+ |
|
+ if (outbuf[0] != 0x41 || outbuf[1] != 0 || outbuf[2] != 0) |
|
+ { |
|
+ puts ("Characters conversion is incorrect!"); |
|
+ result = 1; |
|
+ } |
|
+ |
|
+ iconv_close (cd); |
|
+ |
|
+ return result; |
|
+} |
|
+ |
|
+#define TEST_FUNCTION do_test () |
|
+#include "../test-skeleton.c" |
|
-- |
|
1.8.3.1
|
|
|