This is the mail archive of the
libc-alpha@sourceware.cygnus.com
mailing list for the glibc project.
final iconv call is buggy
- To: libc-alpha at sourceware dot cygnus dot com
- Subject: final iconv call is buggy
- From: Bruno Haible <haible at ilog dot fr>
- Date: Mon, 20 Dec 1999 16:59:44 +0100 (MET)
In glibc-2.1.1, calling iconv(3) with a NULL pointer as inptr (the documented
way to emit the shift sequences which returns to the initial state) produces
wrong results. It produces many output bytes even though the previous
iconv() call has terminated with inbytesleft == 0 and both encodings are
stateless. In this case it should simply return 0 without doing anything.
$ gcc -O foo.c
$ a.out
Before normal iconv call: inptr = 0x8048780, insize = 48, outptr = 0xbfffe708, outsize = 4096
After normal iconv call: inptr = 0x80487b0, insize = 0, outptr = 0xbfffe738, outsize = 4048
Output bytes produced in this call: 48
Before final iconv call: outptr = 0xbfffe708, outsize = 4096
After final iconv call: outptr = 0xbfffe738, outsize = 4048
Output bytes produced in this call: 48
So the total number of bytes produced is 96, although the string is really
only 48 bytes long.
Bruno
============================= foo.c ==========================================
#include <stdio.h>
#include <iconv.h>
#include <errno.h>
int main ()
{
iconv_t cd = iconv_open ("UTF-8", "ISO-8859-1");
const char *start = "This is an _uninteresting_ string of length 47.";
const char *end = start + strlen (start) + 1;
size_t dummy = 0;
size_t length;
char *result;
/* Determine the length we need. */
iconv (cd, NULL, NULL, NULL, &dummy);
{
size_t count = 0;
char tmpbuf[4096];
const char *inptr = start;
size_t insize = end - start;
while (insize > 0)
{
char *outptr = tmpbuf;
size_t outsize = sizeof(tmpbuf);
size_t res;
printf ("Before normal iconv call: inptr = %p, insize = %zd, outptr = %p, outsize = %zd\n", inptr, insize, outptr, outsize);
res = iconv (cd, &inptr, &insize, &outptr, &outsize);
printf ("After normal iconv call: inptr = %p, insize = %zd, outptr = %p, outsize = %zd\n", inptr, insize, outptr, outsize);
printf ("Output bytes produced in this call: %zd\n\n", outptr - tmpbuf);
if (res == (size_t)(-1))
{
if (errno == EINVAL)
break;
else
return 1;
}
count += outptr - tmpbuf;
}
{
char *outptr = tmpbuf;
size_t outsize = sizeof(tmpbuf);
size_t res;
printf ("Before final iconv call: outptr = %p, outsize = %zd\n", outptr, outsize);
res = iconv (cd, NULL, NULL, &outptr, &outsize);
printf ("After final iconv call: outptr = %p, outsize = %zd\n", outptr, outsize);
printf ("Output bytes produced in this call: %zd\n\n", outptr - tmpbuf);
if (res == (size_t)(-1))
return 1;
count += outptr - tmpbuf;
}
length = count;
}
return 0;
}
===============================================================================