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

Bug#39762: iconv() with NULL inbuf gives strange results



Package: gconv-modules
Version: 2.1.1-12
Severity: normal

According to the libc info pages:

     If INBUF is a null pointer the `iconv' function performs the
     necessary action to put the state of the conversion into the
     initial state.

But if inbuf is passed as a NULL pointer, then the values of outbuf
and outbytesleft get changed to especially unuseful values.  For
example, given the program included below:

$ ./iconvnull l1 l1
< iconv_open("l1", "l1")
    => 0x805c7d0
< iconv(0x805c7d0, (nil), 0, 0x8049be0, 80)
>       0x805c7d0, (nil), 0, (nil), 134519856
    => 0
< iconv_close(0x805c7d0)
    => 0

Note that 0x8049be0 + 80 = 134519856.  In this particular case, since
the transformation is the identity, I wouldn't expect *any* changes,
but the same results are obtained whatever the character sets, as far
as I can tell.

------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <iconv.h>

#define OUTLEN 80

int
main(int argc, char *argv[])
{
	iconv_t cd;
	const char *inbuf;
	char *outbuf;
	size_t inleft, outleft;
	size_t numconv;
	int status, save_err;

	if (argc < 3) {
		fprintf(stderr, "usage: iconvnull <to> <from>\n");
		exit(EXIT_FAILURE);
	}

	if ((outbuf = malloc(OUTLEN)) == NULL) {
		perror("malloc");
		exit(EXIT_FAILURE);
	}
	outleft = OUTLEN;

	printf("< iconv_open(\"%s\", \"%s\")\n", argv[1], argv[2]);
	cd = iconv_open(argv[1], argv[2]);
	save_err = errno;
	printf("    => %p\n", (void *) cd);
	if (cd == (iconv_t) -1) {
		printf("ERROR: %d (%s)\n", save_err, strerror(save_err));
		exit(EXIT_FAILURE);
	}

	inbuf = NULL;
	inleft = 0;
	printf("< iconv(%p, %p, %ld, %p, %ld)\n",
	       (void *) cd, inbuf, (long) inleft, outbuf, (long) outleft);
	numconv = iconv(cd, &inbuf, &inleft, &outbuf, &outleft);
	save_err = errno;
	printf(">       %p, %p, %ld, %p, %ld\n",
	       (void *) cd, inbuf, (long) inleft, outbuf, (long) outleft);
	printf("    => %ld\n", (long) numconv);
	if (numconv == (size_t) -1) {
		printf("ERROR: %d (%s)\n", save_err, strerror(save_err));
		exit(EXIT_FAILURE);
	}

	printf("< iconv_close(%p)\n", (void *) cd);
	status = iconv_close(cd);
	save_err = errno;
	printf("    => %d\n", status);
	if (status == -1) {
		printf("ERROR: %d (%s)\n", save_err, strerror(save_err));
		exit(EXIT_FAILURE);
	}

	exit(EXIT_SUCCESS);
}
------------------------------------------------------------

-- System Information
Debian Release: potato
Architecture: i386
Kernel: Linux psyche 2.2.10 #1 Mon Jun 14 21:38:15 NZST 1999 i586

Versions of packages gconv-modules depends on:
ii  libc6           2.1.1-12       GNU C Library: Shared libraries and timezone


Reply to: