This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
bug involving open_memstream() streams and wide operations
- From: mjn3 at codepoet dot org (Manuel Novoa III)
- To: libc-alpha at sources dot redhat dot com
- Date: Sat, 13 Sep 2003 16:50:18 -0600
- Subject: bug involving open_memstream() streams and wide operations
Hello,
Streams created with open_memstream() are unoriented at creation and
wide output operations return success. However, the results are
incorrect. Illustrative app attached.
Manuel
/* Illustration of open_memstream bug with wide output.
Output for glibc -- cvs Sep 10 14:37 CDT
Apparently, streams created with open_memstream() are unoriented
and allow wide output to take place. Unfortunately, the results
are incorrect.
Note that streams created with fmemopen() and fopencookie()
appear to have byte orientation at creation. This limitation
doesn't appear to be documented. Was it intentional or is it
a bug?
----------- output -----------
locale: en_US.UTF-8
fmemopen -------
pre-output : fwide(f, 0) = -1
wide output is not supported
open_memstream -------
pre-output : fwide(f, 0) = 0
post-output: fwide(f, 0) = 1
buf != string stream buf
snprintf buf : len = 2 : bytes - 0xce 0xa9
string stream : len = 2 : bytes - 0xa9 0x03
fopencookie -------
pre-output : fwide(f, 0) = -1
wide output is not supported
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <locale.h>
#include <wchar.h>
#include <unistd.h>
static const char locale[] = "en_US.UTF-8";
#define NBUF 128
struct cs {
int n;
char buf[NBUF];
};
static ssize_t c_write(void *p, const char *b, size_t n)
{
if ((((struct cs *)p)->n + n) >= NBUF) {
return -1;
}
memcpy(((struct cs *)p)->buf + ((struct cs *)p)->n, b, n);
((struct cs *)p)->n += n;
return n;
}
static int c_close(void *p)
{
/* just nul-terminate */
*(((struct cs *)p)->buf + ((struct cs *)p)->n) = 0;
return 0;
}
static const cookie_io_functions_t ciof = {
NULL,
c_write,
NULL,
c_close
};
int main(int argc, char **argv)
{
char buf[NBUF];
char fmobuf[NBUF];
char *p;
size_t m;
FILE *f;
wint_t wc = L'\x03A9';
int retval = EXIT_SUCCESS;
int i, n;
struct cs cookie;
memset(&cookie, 0, sizeof(cookie));
if (!setlocale(LC_ALL, locale)) {
fprintf(stderr, "setlocale for %s failed!\n", locale);
return EXIT_FAILURE;
}
fprintf(stderr, "locale: %s\n", locale);
if (snprintf(buf, NBUF, "%lc", wc) <= 0) {
fprintf(stderr, "snprintf failed!\n");
return EXIT_FAILURE;
}
for (i=0 ; i < 3 ; i++ ) {
if (i == 0) {
p = fmobuf;
fprintf(stderr, "\nfmemopen -------\n");
if (!(f = fmemopen(p, NBUF - 1, "w"))) {
fprintf(stderr, "fmemopen failed!\n");
retval = EXIT_FAILURE;
continue;
}
} else if (i == 1) {
fprintf(stderr, "\nopen_memstream -------\n");
if (!(f = open_memstream(&p, &m))) {
fprintf(stderr, "open_memstream failed!\n");
retval = EXIT_FAILURE;
continue;
}
} else {
fprintf(stderr, "\nfopencookie -------\n");
if (!(f = fopencookie (&cookie, "w", ciof))) {
fprintf(stderr, "fopencookie failed!\n");
retval = EXIT_FAILURE;
continue;
}
}
n = fwide(f, 0);
fprintf(stderr, "pre-output : fwide(f, 0) = %d\n", n);
if (n < 0) {
fprintf(stderr, "wide output is not supported\n");
fclose(f);
continue;
}
if (fputwc(wc, f) == WEOF) {
fprintf(stderr, "fputc failed!\n");
fclose(f);
retval = EXIT_FAILURE;
continue;
}
if (fflush(f)) {
fprintf(stderr, "fflush failed!\n");
fclose(f);
continue;
}
fprintf(stderr, "post-output: fwide(f, 0) = %d\n", fwide(f, 0));
if (fclose(f)) {
fprintf(stderr, "fclose failed!\n");
continue;
}
if (strcmp(buf, p)) {
unsigned char *s;
fprintf(stderr, "buf != string stream buf\n");
fprintf(stderr, "snprintf buf : len = %d : bytes -", strlen(buf));
for (s = (unsigned char *) buf ; *s ; s++) {
fprintf(stderr, " %#04x", *s);
}
fprintf(stderr, "\n");
fprintf(stderr, "string stream : len = %d : bytes -", strlen(buf));
for (s = (unsigned char *) p ; *s ; s++) {
fprintf(stderr, " %#04x", *s);
}
fprintf(stderr, "\n");
retval = EXIT_FAILURE;
continue;
}
}
fprintf(stderr, "\n");
return retval;
}