This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc 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]

Out out bounds array access in ibm iconv bits


So AFAICT this is a true error in the ibm iconv code spotted by Martin's
improvements to the out of bounds array indexing warning on the gcc trunk.

Building trunk glibc with a trunk gcc (any target AFAICT) on results in
a warning like this:

In file included from ibm1364.c:393,
                 from ibm1390.c:35:
../iconv/skeleton.c: In function ‘gconv’:
../iconv/loop.c:446:274: error: array subscript 1 is outside array
bounds of ‘unsigned char[4]’ [-Werror=array-bounds]
       BODY


There's a truly *horrid* maze of twisty #defines in play here.  After
preprocessing it looks like this:


static inline int
__attribute ((always_inline))
to_ibm1390_single (struct __gconv_step *step,
   struct __gconv_step_data *step_data,
   const unsigned char **inptrp, const unsigned char *inend,
   unsigned char **outptrp, unsigned char *outend,
   size_t *irreversible , int *curcsp)
{
  mbstate_t *state = step_data->__statep;
  int flags = step_data->__flags;
  int result = __GCONV_OK;
  unsigned char bytebuf[4];
[ ... ]
  inptr = bytebuf;
[ ... ]
    { uint32_t ch = *((const uint32_t *) (inptr)); if (__builtin_expect
((ch >= 0xffffffff), 0)) { { if (((ch) >> 7) == (0xe0000 >> 7)) { inptr
+= 4; continue; } }; if (! (irreversible != ((void *)0) && (flags &
__GCONV_IGNORE_ERRORS))) { result = __GCONV_ILLEGAL_INPUT; break; }
++*irreversible; inptr += 4; continue; } { const struct combine *cmbp =
__ucs4_combined_to_ibm1390db; while (cmbp->res1 < ch) ++cmbp; if
(cmbp->res1 == ch && inptr + 4 < inend) { uint32_t ch_next = *((const
uint32_t *) (inptr + 4));

[ Insanely long line truncated ]

Note the dereference *((const uint32_t *) (inptr + 4))

Boom, that's out of bounds.  inptr points to bytebuf which is just 4
bytes in size, thus *(inptr+4) is bad.  Now perhaps there's something
buried in this mess that prevents the code in question from ever
executing, but I don't see what it would be.  The inptr + 4 < inend
guard seems like it might, but inend is an incoming parameter, so the
condition doesn't really tell the compiler anything useful.  In fact it
looks like we're comparing pointers to two completely unrelated objects.


Anyway, I'm heading out on PTO shortly.  So someone else will need to
pick up the ball here.

Jeff



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