Module Name: src Committed By: roy Date: Tue Dec 1 00:03:53 UTC 2009
Modified Files: src/lib/libc/stdio: fgetstr.c getdelim.c local.h Log Message: Remove __getdelim and just use getdelim. fgetstr now works with strings up to SSIZE_MAX as a result, but may reallocate buffers needlessly just like it used to when the buffer size exceeds INT_MAX. fgetstr converts errno EOVERFLOW to EINVAL on getdelim error. To generate a diff of this commit: cvs rdiff -u -r1.8 -r1.9 src/lib/libc/stdio/fgetstr.c cvs rdiff -u -r1.7 -r1.8 src/lib/libc/stdio/getdelim.c cvs rdiff -u -r1.21 -r1.22 src/lib/libc/stdio/local.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/stdio/fgetstr.c diff -u src/lib/libc/stdio/fgetstr.c:1.8 src/lib/libc/stdio/fgetstr.c:1.9 --- src/lib/libc/stdio/fgetstr.c:1.8 Thu Oct 15 00:36:24 2009 +++ src/lib/libc/stdio/fgetstr.c Tue Dec 1 00:03:53 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: fgetstr.c,v 1.8 2009/10/15 00:36:24 roy Exp $ */ +/* $NetBSD: fgetstr.c,v 1.9 2009/12/01 00:03:53 roy Exp $ */ /* * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: fgetstr.c,v 1.8 2009/10/15 00:36:24 roy Exp $"); +__RCSID("$NetBSD: fgetstr.c,v 1.9 2009/12/01 00:03:53 roy Exp $"); #include "namespace.h" @@ -51,24 +51,28 @@ { char *p; size_t size; + ssize_t n; _DIAGASSERT(fp != NULL); _DIAGASSERT(lenp != NULL); p = (char *)fp->_lb._base; size = fp->_lb._size; - *lenp = __getdelim(&p, &size, sep, fp); + n = getdelim(&p, &size, sep, fp); fp->_lb._base = (unsigned char *)p; - /* The struct size variable is only an int ..... */ - if (size > INT_MAX) { + /* The struct size variable is only an int ..... + * This still works when exceeded, but the buffer could be + * realloced needlessly. */ + if (size > INT_MAX) fp->_lb._size = INT_MAX; - errno = EOVERFLOW; - goto error; + else + fp->_lb._size = (int)size; + if (n == -1) { + *lenp = 0; + if (errno == EOVERFLOW) /* fixup errno */ + errno = EINVAL; + return NULL; } - fp->_lb._size = (int)size; - if (*lenp != 0 && *lenp < SIZE_MAX - 1) - return p; -error: - *lenp = 0; - return NULL; + *lenp = n; + return p; } Index: src/lib/libc/stdio/getdelim.c diff -u src/lib/libc/stdio/getdelim.c:1.7 src/lib/libc/stdio/getdelim.c:1.8 --- src/lib/libc/stdio/getdelim.c:1.7 Sun Oct 25 20:44:13 2009 +++ src/lib/libc/stdio/getdelim.c Tue Dec 1 00:03:53 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: getdelim.c,v 1.7 2009/10/25 20:44:13 christos Exp $ */ +/* $NetBSD: getdelim.c,v 1.8 2009/12/01 00:03:53 roy Exp $ */ /* * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: getdelim.c,v 1.7 2009/10/25 20:44:13 christos Exp $"); +__RCSID("$NetBSD: getdelim.c,v 1.8 2009/12/01 00:03:53 roy Exp $"); #include "namespace.h" @@ -49,11 +49,8 @@ * without the need for a realloc. */ #define MINBUF 128 -/* This private function allows strings of upto SIZE_MAX - 2 - * and returns 0 on EOF, both of which are disallowed by POSIX. - * Maybe this should be named fgetdelim and proposed to the OpenGroup....*/ ssize_t -__getdelim(char **__restrict buf, size_t *__restrict buflen, +getdelim(char **__restrict buf, size_t *__restrict buflen, int sep, FILE *__restrict fp) { unsigned char *p; @@ -74,11 +71,12 @@ FLOCKFILE(fp); _SET_ORIENTATION(fp, -1); off = 0; - for (;;) { + do { /* If the input buffer is empty, refill it */ if (fp->_r <= 0 && __srefill(fp)) { if (__sferror(fp)) goto error; + /* No error, so EOF. */ break; } @@ -91,7 +89,7 @@ newlen = off + len + 1; /* Ensure we can handle it */ - if (newlen < off || newlen > SIZE_MAX - 2) { + if (newlen < off || newlen > (size_t)SSIZE_MAX + 1) { errno = EOVERFLOW; goto error; } @@ -124,33 +122,19 @@ fp->_r -= (int)len; fp->_p += (int)len; off += len; - if (p != NULL) - break; - } + } while (p == NULL); FUNLOCKFILE(fp); + + /* POSIX demands we return -1 on EOF. */ + if (off == 0) + return -1; + if (*buf != NULL) *(*buf + off) = '\0'; return off; error: + fp->_flags |= __SERR; FUNLOCKFILE(fp); return -1; } - -ssize_t -getdelim(char **__restrict buf, size_t *__restrict buflen, - int sep, FILE *__restrict fp) -{ - ssize_t len; - - len = __getdelim(buf, buflen, sep, fp); - if (len == 0) { - /* POSIX requires that we return -1 on EOF */ - return -1; - } else if (len < -1) { - /* POSIX requires no string larger than SSIZE_MAX */ - errno = EOVERFLOW; - return -1; - } - return len; -} Index: src/lib/libc/stdio/local.h diff -u src/lib/libc/stdio/local.h:1.21 src/lib/libc/stdio/local.h:1.22 --- src/lib/libc/stdio/local.h:1.21 Thu Sep 24 20:38:53 2009 +++ src/lib/libc/stdio/local.h Tue Dec 1 00:03:53 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: local.h,v 1.21 2009/09/24 20:38:53 roy Exp $ */ +/* $NetBSD: local.h,v 1.22 2009/12/01 00:03:53 roy Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -75,8 +75,6 @@ extern wint_t __fgetwc_unlock __P((FILE *)); extern wint_t __fputwc_unlock __P((wchar_t, FILE *)); -extern ssize_t __getdelim __P((char ** __restrict, size_t * __restrict, int, - FILE * __restrict)); extern char *__fgetstr __P((FILE * __restrict, size_t * __restrict, int)); extern int __vfwprintf_unlocked __P((FILE *, const wchar_t *, _BSD_VA_LIST_));