Bug#406946: iconv() crashes during ASCII -> WCHAR_T conversion on sparc
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
jurij@debian:~$ gcc -g iconv-crash.c
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".
Starting program: /home/jurij/iconv-crash
Program received signal SIGBUS, Bus error.
0xf7e7a1f4 in __gconv_transform_internal_ascii () from /lib/libc.so.6
#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); \
/* 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.
Jurij Smakov firstname.lastname@example.org
Key: http://www.wooyd.org/pgpkey/ KeyID: C99E03CC
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);