This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]