This is the mail archive of the libc-locales@sourceware.org mailing list for the GNU libc locales project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug localedata/17325] New: iconv from ccsid 937 to utf-8 access invalid memory


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]