OSDN Git Service

Fix (hopefully) scanf behavior for nul bytes in the stream when processing
authorManuel Novoa III <mjn3@codepoet.org>
Thu, 15 May 2003 21:32:31 +0000 (21:32 -0000)
committerManuel Novoa III <mjn3@codepoet.org>
Thu, 15 May 2003 21:32:31 +0000 (21:32 -0000)
%c, %s, and %[ specifiers.  Note that scanf is undergoing rewrite so I
didn't bother optimizing this.  I did run all my regression tests though.
Set EOF correctly for fmemopen on readonly streams.  I really need to
check what glibc behavior is for the various open modes though.

libc/stdio/scanf.c
libc/stdio/stdio.c

index 7c316cd..4fbf1cd 100644 (file)
@@ -32,6 +32,9 @@
  *
  * Sep 6, 2002
  * Patch from Tero_Lyytikäinen <tero@paravant.fi> to fix bug in matchchar case.
+ *
+ * May 15, 2003
+ * Hopefully fix handling of 0 bytes with %s, %c, and %[ specifiers.
  */
 
 #define _ISOC99_SOURCE                 /* for LLONG_MAX primarily... */
@@ -122,10 +125,10 @@ int vsscanf(__const char *sp, __const char *fmt, va_list ap)
 {
        FILE string[1];
 
-       string->filedes = -2;           /* for debugging */
+       string->filedes = -2;
        string->modeflags = (__FLAG_NARROW|__FLAG_READONLY);
        string->bufstart = string->bufpos = (unsigned char *) ((void *) sp);
-       string->bufgetc = (char *) ((unsigned) -1);
+       string->bufgetc = string->bufstart + strlen(sp);
 
 #ifdef __STDIO_MBSTATE
        __INIT_MBSTATE(&(string->state));
@@ -241,7 +244,7 @@ static int scan_getc(register struct scan_cookie *sc)
        sc->width_flag = 1;
        if (--sc->width < 0) {
                sc->ungot_flag = 1;
-               return 0;
+               return -1;
        }
        sc->ungot_flag = 0;
        if (sc->ungot_char > 0) {
@@ -347,7 +350,7 @@ int vfscanf(FILE *fp, const char *format, va_list ap)
                                if (p-spec < 5) { /* [,c,s - string conversions */
                                        invert = 0;
                                        if (*p == 'c') {
-                                               invert = 1;
+                                               invert = 0;
                                                if (sc.width == INT_MAX) {
                                                        sc.width = 1;
                                                }
@@ -399,12 +402,16 @@ int vfscanf(FILE *fp, const char *format, va_list ap)
                                                b = buf;
                                        }
                                        cc = scan_getc(&sc);
-                                       if (cc <= 0) {
+                                       if (cc < 0) {
                                                scan_ungetc(&sc);
                                                goto done; /* return EOF if cnt == 0 */
                                        }
+                                       if (*p == 'c') {
+                                               goto c_spec;
+                                       }
                                        i = 0;
-                                       while ((cc>0) && (scanset[cc] != invert)) {
+                                       while ((cc>=0) && (scanset[cc] != invert)) {
+                                       c_spec:
                                                i = 1; /* yes, we stored something */
                                                *b = cc;
                                                b += store;
index 0599f23..eec8bdd 100644 (file)
  *  Also fix _stdio_fopen to support fdopen() with append specified when
  *     the underlying file didn't have O_APPEND set.  It now sets the
  *     O_APPEND flag as recommended by SUSv3 and is done by glibc.
+ *
+ *  May 15, 2003
+ *  Modify __stdio_fread to deal with fake streams used by *sscanf.
+ *  Set EOF to end of buffer when fmemopen used on a readonly stream.
+ *    Note: I really need to run some tests on this to see what the
+ *    glibc code does in each case.
  */
 
 /* Before we include anything, convert L_ctermid to L_ctermid_function
@@ -639,6 +645,9 @@ FILE *fmemopen(void *s, size_t len, const char *modes)
 
                if (fp != NULL) {
                        cookie->fp = fp;
+                       if (fp->modeflags & __FLAG_READONLY) {
+                               cookie->eof = len;
+                       }
                        if ((fp->modeflags & __FLAG_APPEND) && (len > 0)) {
                                for (i = 0 ; i < len ; i++) {
                                        if (cookie->buf[i] == 0) {
@@ -1406,7 +1415,7 @@ size_t _stdio_fread(unsigned char *buffer, size_t bytes, register FILE *stream)
                        *p++ = *stream->bufpos++;
                }
 
-               if (bytes > 0) {
+               if ((bytes > 0) && (stream->filedes != -2)) {
                        ssize_t len;
 
                        /* The buffer is exhausted, but we still need chars.  */