This is the mail archive of the
libc-locales@sourceware.org
mailing list for the GNU libc locales project.
[Bug localedata/17325] New: iconv from ccsid 937 to utf-8 access invalid memory
- From: "azanella at linux dot vnet.ibm.com" <sourceware-bugzilla at sourceware dot org>
- To: libc-locales at sourceware dot org
- Date: Thu, 28 Aug 2014 17:46:05 +0000
- Subject: [Bug localedata/17325] New: iconv from ccsid 937 to utf-8 access invalid memory
- Auto-submitted: auto-generated
https://sourceware.org/bugzilla/show_bug.cgi?id=17325
Bug ID: 17325
Summary: iconv from ccsid 937 to utf-8 access invalid memory
Product: glibc
Version: 2.20
Status: NEW
Severity: normal
Priority: P2
Component: localedata
Assignee: unassigned at sourceware dot org
Reporter: azanella at linux dot vnet.ibm.com
CC: libc-locales at sourceware dot org
The testcase:
--
#include <stdio.h>
#include <stdlib.h>
#include <iconv.h>
void
testIconv (const char *toEnc, char *to_conv, size_t to_conv_len)
{
iconv_t cd;
char buf_input[13];
char buf_output[64];
size_t input_len = to_conv_len;
sprintf (buf_input, "%s", to_conv);
size_t available_len = sizeof (buf_output) - 1;
size_t output_len = available_len;
buf_output[sizeof (buf_output) - 1] = 0;
cd = iconv_open ("UTF-8", toEnc);
if (cd == (iconv_t) - 1)
{
fprintf (stderr, "%s: iconv_open (...) error\n", toEnc);
return;
}
char *in_buf_ptr = &buf_input[0];
char *out_buf_ptr = &buf_output[0];
size_t iconv_val =
iconv (cd, &in_buf_ptr, &input_len, &out_buf_ptr, &output_len);
if (iconv_val == (size_t) - 1)
{
fprintf (stderr, "%s: iconv (...) error\n", toEnc);
return;
}
size_t converted = available_len - output_len;
if (converted > 0 && converted < sizeof (buf_output))
{
buf_output[converted] = 0;
fprintf (stderr, "%s: converted to %s\n", toEnc, buf_output);
}
int ret = iconv_close (cd);
if (ret != 0)
fprintf (stderr, "%s: iconv_close(...) err\n", toEnc);
}
int
main ()
{
testIconv ("IBM930", "\016\377\377\377\377\377\377\377\377\377\377\377", 12);
testIconv ("IBM932", "\016\377\377\377\377\377\377\377\377\377\377\377", 12);
testIconv ("IBM933", "\016\377\377\377\377\377\377\377\377\377\377\377", 12);
testIconv ("IBM935", "\016\377\377\377\377\377\377\377\377\377\377\377", 12);
testIconv ("IBM937", "\016\377\377\377\377\377\377\377\377\377\377\377", 12);
testIconv ("IBM939", "\016\377\377\377\377\377\377\377\377\377\377\377", 12);
testIconv ("IBM943", "\016\377\377\377\377\377\377\377\377\377\377\377", 12);
return 0;
}
--
Produces segmentation faults due invalid memory access, more specifically, on
GLIBC's code:
* iconvdata/ibm937.c
161 ch = (ch * 0x100) + inptr[1];
\
162 while (ch > rp2->end)
\
163 ++rp2;
\
164
\
165 if (__builtin_expect (rp2 == NULL, 0)
\
166 || __builtin_expect (ch < rp2->start, 0)
\
167 || (res = __ibm937db_to_ucs4[ch + rp2->idx],
\
168 __builtin_expect (res, L'\1') == L'\0' && ch != '\0'))
\
169 {
\
170 /* This is an illegal character. */
\
171 STANDARD_FROM_LOOP_ERR_HANDLER (2);
\
172 }
\
173 else
\
174 {
\
175 put32 (outptr, res);
\
176 outptr += 4;
\
177 }
\
178 inptr += 2;
\
179 }
\
The 'res = __ibm937db_to_ucs4[ch + rp2->idx],' is accessing invalid memory due
the array index value 'ch + rp2->idx' being out the bounds. A straightforward
fix you emit an invalid error if the index is out of the bonds, as the
following:
diff --git a/iconvdata/ibm933.c b/iconvdata/ibm933.c
index f46dfb5..6de73e8 100644
--- a/iconvdata/ibm933.c
+++ b/iconvdata/ibm933.c
@@ -164,6 +164,8 @@ enum
\
if (__builtin_expect (rp2 == NULL, 0) \
|| __builtin_expect (ch < rp2->start, 0) \
+ || __builtin_expect ( \
+ (ch + rp2->idx) > sizeof __ibm933db_to_ucs4, 0) \
|| (res = __ibm933db_to_ucs4[ch + rp2->idx], \
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
{ \
diff --git a/iconvdata/ibm935.c b/iconvdata/ibm935.c
index a8e4e6c..dfb152d 100644
--- a/iconvdata/ibm935.c
+++ b/iconvdata/ibm935.c
@@ -164,6 +164,8 @@ enum
\
if (__builtin_expect (rp2 == NULL, 0) \
|| __builtin_expect (ch < rp2->start, 0) \
+ || __builtin_expect ( \
+ (ch + rp2->idx) > sizeof __ibm935db_to_ucs4, 0) \
|| (res = __ibm935db_to_ucs4[ch + rp2->idx], \
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
{ \
diff --git a/iconvdata/ibm937.c b/iconvdata/ibm937.c
index 239be61..13f8b3c 100644
--- a/iconvdata/ibm937.c
+++ b/iconvdata/ibm937.c
@@ -164,6 +164,8 @@ enum
\
if (__builtin_expect (rp2 == NULL, 0) \
|| __builtin_expect (ch < rp2->start, 0) \
+ || __builtin_expect ( \
+ (ch + rp2->idx) > sizeof __ibm937db_to_ucs4, 0) \
|| (res = __ibm937db_to_ucs4[ch + rp2->idx], \
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
{ \
diff --git a/iconvdata/ibm939.c b/iconvdata/ibm939.c
index 5d0db36..98299e9 100644
--- a/iconvdata/ibm939.c
+++ b/iconvdata/ibm939.c
@@ -164,6 +164,8 @@ enum
\
if (__builtin_expect (rp2 == NULL, 0) \
|| __builtin_expect (ch < rp2->start, 0) \
+ || __builtin_expect ( \
+ (ch + rp2->idx) > sizeof __ibm939db_to_ucs4, 0) \
|| (res = __ibm939db_to_ucs4[ch + rp2->idx], \
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
{
--
You are receiving this mail because:
You are on the CC list for the bug.