[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#406946: iconv() crashes during ASCII -> WCHAR_T conversion on sparc

Package: libc6
Version: 2.3.6.ds1-10
Severity: important


The iconv() function may die with bus error due to unaligned memory 
accesses on sparc and, probably, other platforms with strict alignment 
requirements. It can be occasionally triggered by attempting 'aptitude 
install non-existent-package' (thanks to Al Viro and Fabio M. Di Nitto 
for the report and initial investigation). It also affects etch 
version (2.3.6.ds1-8) as well. The test case (attached) illustrates 
the problem:

jurij@debian:~$ gcc -g iconv-crash.c 
jurij@debian:~$ ./iconv-crash 
Bus error
jurij@debian:~$ gdb ./iconv-crash 
GNU gdb 6.5-debian
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "sparc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) run
Starting program: /home/jurij/iconv-crash 

Program received signal SIGBUS, Bus error.
0xf7e7a1f4 in __gconv_transform_internal_ascii () from /lib/libc.so.6
(gdb) bt
#0  0xf7e7a1f4 in __gconv_transform_internal_ascii () from 
#1  0xf7e75df4 in __gconv () from /lib/libc.so.6
#2  0xf7e752a8 in iconv () from /lib/libc.so.6
#3  0x000105e0 in main () at iconv-crash.c:15

AFAICT, the body of the __gconv_transform_internal_ascii() is defined 
in iconv/gconv_simple.c as

#define BODY \
  {                                                                           \
    if (__builtin_expect (*((const uint32_t *) inptr) > 0x7f, 0))             \
      {                                                                       \
        UNICODE_TAG_HANDLER (*((const uint32_t *) inptr), 4);                 \
        STANDARD_TO_LOOP_ERR_HANDLER (4);                                     \
      }                                                                       \
    else                                                                      \
      /* It's an one byte sequence.  */                                       \
      *outptr++ = *((const uint32_t *) inptr);                                \
      inptr += sizeof (uint32_t);                                             \

The word-sized accesses at the potentially unaligned location 
pointed to by inptr are likely to be causing the problem.

Best regards,
Jurij Smakov                                           jurij@wooyd.org
Key: http://www.wooyd.org/pgpkey/                      KeyID: C99E03CC
#include <stdio.h>
#include <stdlib.h>
#include <iconv.h>
#include <string.h>

int main()
        iconv_t cd;
        size_t inr = 4, outr = 8, res;
        char *inbuf = strdup("abcde");
        char *outbuf = malloc(8);

        cd = iconv_open("ASCII", "WCHAR_T");
        res = iconv(cd, &inbuf, &inr, &outbuf, &outr);

        return 0;

Reply to: