Tue Dec 1 00:03:53 2009 UTC ()
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.


(roy)
diff -r1.8 -r1.9 src/lib/libc/stdio/fgetstr.c
diff -r1.7 -r1.8 src/lib/libc/stdio/getdelim.c
diff -r1.21 -r1.22 src/lib/libc/stdio/local.h

cvs diff -r1.8 -r1.9 src/lib/libc/stdio/fgetstr.c (expand / switch to unified diff)

--- src/lib/libc/stdio/fgetstr.c 2009/10/15 00:36:24 1.8
+++ src/lib/libc/stdio/fgetstr.c 2009/12/01 00:03:53 1.9
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: fgetstr.c,v 1.8 2009/10/15 00:36:24 roy Exp $ */ 1/* $NetBSD: fgetstr.c,v 1.9 2009/12/01 00:03:53 roy Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * 5 *
6 * This code is derived from software contributed to The NetBSD Foundation 6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Roy Marples. 7 * by Roy Marples.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -18,57 +18,61 @@ @@ -18,57 +18,61 @@
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31__RCSID("$NetBSD: fgetstr.c,v 1.8 2009/10/15 00:36:24 roy Exp $"); 31__RCSID("$NetBSD: fgetstr.c,v 1.9 2009/12/01 00:03:53 roy Exp $");
32 32
33#include "namespace.h" 33#include "namespace.h"
34 34
35#include <assert.h> 35#include <assert.h>
36#include <errno.h> 36#include <errno.h>
37#include <limits.h> 37#include <limits.h>
38#include <stdio.h> 38#include <stdio.h>
39 39
40#include "reentrant.h" 40#include "reentrant.h"
41#include "local.h" 41#include "local.h"
42 42
43/* 43/*
44 * Get an input line. 44 * Get an input line.
45 * This now uses getdelim(3) for a code reduction. 45 * This now uses getdelim(3) for a code reduction.
46 * The upside is that strings are now always NULL terminated, but relying 46 * The upside is that strings are now always NULL terminated, but relying
47 * on this is non portable - better to use the POSIX getdelim(3) function. 47 * on this is non portable - better to use the POSIX getdelim(3) function.
48 */ 48 */
49char * 49char *
50__fgetstr(FILE *__restrict fp, size_t *__restrict lenp, int sep) 50__fgetstr(FILE *__restrict fp, size_t *__restrict lenp, int sep)
51{ 51{
52 char *p; 52 char *p;
53 size_t size; 53 size_t size;
 54 ssize_t n;
54 55
55 _DIAGASSERT(fp != NULL); 56 _DIAGASSERT(fp != NULL);
56 _DIAGASSERT(lenp != NULL); 57 _DIAGASSERT(lenp != NULL);
57 58
58 p = (char *)fp->_lb._base; 59 p = (char *)fp->_lb._base;
59 size = fp->_lb._size; 60 size = fp->_lb._size;
60 *lenp = __getdelim(&p, &size, sep, fp); 61 n = getdelim(&p, &size, sep, fp);
61 fp->_lb._base = (unsigned char *)p; 62 fp->_lb._base = (unsigned char *)p;
62 /* The struct size variable is only an int ..... */ 63 /* The struct size variable is only an int .....
63 if (size > INT_MAX) { 64 * This still works when exceeded, but the buffer could be
 65 * realloced needlessly. */
 66 if (size > INT_MAX)
64 fp->_lb._size = INT_MAX; 67 fp->_lb._size = INT_MAX;
65 errno = EOVERFLOW; 68 else
66 goto error; 69 fp->_lb._size = (int)size;
 70 if (n == -1) {
 71 *lenp = 0;
 72 if (errno == EOVERFLOW) /* fixup errno */
 73 errno = EINVAL;
 74 return NULL;
67 } 75 }
68 fp->_lb._size = (int)size; 76 *lenp = n;
69 if (*lenp != 0 && *lenp < SIZE_MAX - 1) 77 return p;
70 return p; 
71error: 
72 *lenp = 0; 
73 return NULL; 
74} 78}

cvs diff -r1.7 -r1.8 src/lib/libc/stdio/getdelim.c (expand / switch to unified diff)

--- src/lib/libc/stdio/getdelim.c 2009/10/25 20:44:13 1.7
+++ src/lib/libc/stdio/getdelim.c 2009/12/01 00:03:53 1.8
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: getdelim.c,v 1.7 2009/10/25 20:44:13 christos Exp $ */ 1/* $NetBSD: getdelim.c,v 1.8 2009/12/01 00:03:53 roy Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * 5 *
6 * This code is derived from software contributed to The NetBSD Foundation 6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Roy Marples. 7 * by Roy Marples.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -18,90 +18,88 @@ @@ -18,90 +18,88 @@
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31__RCSID("$NetBSD: getdelim.c,v 1.7 2009/10/25 20:44:13 christos Exp $"); 31__RCSID("$NetBSD: getdelim.c,v 1.8 2009/12/01 00:03:53 roy Exp $");
32 32
33#include "namespace.h" 33#include "namespace.h"
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36 36
37#include <assert.h> 37#include <assert.h>
38#include <errno.h> 38#include <errno.h>
39#include <limits.h> 39#include <limits.h>
40#include <stdio.h> 40#include <stdio.h>
41#include <stdlib.h> 41#include <stdlib.h>
42#include <string.h> 42#include <string.h>
43 43
44#include "reentrant.h" 44#include "reentrant.h"
45#include "local.h" 45#include "local.h"
46 46
47/* Minimum buffer size we create. 47/* Minimum buffer size we create.
48 * This should allow config files to fit into our power of 2 buffer growth 48 * This should allow config files to fit into our power of 2 buffer growth
49 * without the need for a realloc. */ 49 * without the need for a realloc. */
50#define MINBUF 128 50#define MINBUF 128
51 51
52/* This private function allows strings of upto SIZE_MAX - 2 
53 * and returns 0 on EOF, both of which are disallowed by POSIX. 
54 * Maybe this should be named fgetdelim and proposed to the OpenGroup....*/ 
55ssize_t 52ssize_t
56__getdelim(char **__restrict buf, size_t *__restrict buflen, 53getdelim(char **__restrict buf, size_t *__restrict buflen,
57 int sep, FILE *__restrict fp) 54 int sep, FILE *__restrict fp)
58{ 55{
59 unsigned char *p; 56 unsigned char *p;
60 size_t len, newlen, off; 57 size_t len, newlen, off;
61 char *newb; 58 char *newb;
62 59
63 _DIAGASSERT(fp != NULL); 60 _DIAGASSERT(fp != NULL);
64 61
65 if (buf == NULL || buflen == NULL) { 62 if (buf == NULL || buflen == NULL) {
66 errno = EINVAL; 63 errno = EINVAL;
67 return -1; 64 return -1;
68 } 65 }
69 66
70 /* If buf is NULL, we have to assume a size of zero */ 67 /* If buf is NULL, we have to assume a size of zero */
71 if (*buf == NULL) 68 if (*buf == NULL)
72 *buflen = 0; 69 *buflen = 0;
73 70
74 FLOCKFILE(fp); 71 FLOCKFILE(fp);
75 _SET_ORIENTATION(fp, -1); 72 _SET_ORIENTATION(fp, -1);
76 off = 0; 73 off = 0;
77 for (;;) { 74 do {
78 /* If the input buffer is empty, refill it */ 75 /* If the input buffer is empty, refill it */
79 if (fp->_r <= 0 && __srefill(fp)) { 76 if (fp->_r <= 0 && __srefill(fp)) {
80 if (__sferror(fp)) 77 if (__sferror(fp))
81 goto error; 78 goto error;
 79 /* No error, so EOF. */
82 break; 80 break;
83 } 81 }
84 82
85 /* Scan through looking for the separator */ 83 /* Scan through looking for the separator */
86 p = memchr(fp->_p, sep, (size_t)fp->_r); 84 p = memchr(fp->_p, sep, (size_t)fp->_r);
87 if (p == NULL) 85 if (p == NULL)
88 len = fp->_r; 86 len = fp->_r;
89 else 87 else
90 len = (p - fp->_p) + 1; 88 len = (p - fp->_p) + 1;
91 89
92 newlen = off + len + 1; 90 newlen = off + len + 1;
93 /* Ensure we can handle it */ 91 /* Ensure we can handle it */
94 if (newlen < off || newlen > SIZE_MAX - 2) { 92 if (newlen < off || newlen > (size_t)SSIZE_MAX + 1) {
95 errno = EOVERFLOW; 93 errno = EOVERFLOW;
96 goto error; 94 goto error;
97 } 95 }
98 if (newlen > *buflen) { 96 if (newlen > *buflen) {
99 if (newlen < MINBUF) 97 if (newlen < MINBUF)
100 newlen = MINBUF; 98 newlen = MINBUF;
101 if (!powerof2(newlen)) { 99 if (!powerof2(newlen)) {
102 /* Grow the buffer to the next power of 2 */ 100 /* Grow the buffer to the next power of 2 */
103 newlen--; 101 newlen--;
104 newlen |= newlen >> 1; 102 newlen |= newlen >> 1;
105 newlen |= newlen >> 2; 103 newlen |= newlen >> 2;
106 newlen |= newlen >> 4; 104 newlen |= newlen >> 4;
107 newlen |= newlen >> 8; 105 newlen |= newlen >> 8;
@@ -114,43 +112,29 @@ __getdelim(char **__restrict buf, size_t @@ -114,43 +112,29 @@ __getdelim(char **__restrict buf, size_t
114 112
115 newb = realloc(*buf, newlen); 113 newb = realloc(*buf, newlen);
116 if (newb == NULL) 114 if (newb == NULL)
117 goto error; 115 goto error;
118 *buf = newb; 116 *buf = newb;
119 *buflen = newlen; 117 *buflen = newlen;
120 } 118 }
121 119
122 (void)memcpy((*buf + off), fp->_p, len); 120 (void)memcpy((*buf + off), fp->_p, len);
123 /* Safe, len is never greater than what fp->_r can fit. */ 121 /* Safe, len is never greater than what fp->_r can fit. */
124 fp->_r -= (int)len; 122 fp->_r -= (int)len;
125 fp->_p += (int)len; 123 fp->_p += (int)len;
126 off += len; 124 off += len;
127 if (p != NULL) 125 } while (p == NULL);
128 break; 
129 } 
130 FUNLOCKFILE(fp); 126 FUNLOCKFILE(fp);
 127
 128 /* POSIX demands we return -1 on EOF. */
 129 if (off == 0)
 130 return -1;
 131
131 if (*buf != NULL) 132 if (*buf != NULL)
132 *(*buf + off) = '\0'; 133 *(*buf + off) = '\0';
133 return off; 134 return off;
134 135
135error: 136error:
 137 fp->_flags |= __SERR;
136 FUNLOCKFILE(fp); 138 FUNLOCKFILE(fp);
137 return -1; 139 return -1;
138} 140}
139 
140ssize_t 
141getdelim(char **__restrict buf, size_t *__restrict buflen, 
142 int sep, FILE *__restrict fp) 
143{ 
144 ssize_t len; 
145 
146 len = __getdelim(buf, buflen, sep, fp); 
147 if (len == 0) { 
148 /* POSIX requires that we return -1 on EOF */ 
149 return -1; 
150 } else if (len < -1) { 
151 /* POSIX requires no string larger than SSIZE_MAX */ 
152 errno = EOVERFLOW; 
153 return -1; 
154 } 
155 return len; 
156} 

cvs diff -r1.21 -r1.22 src/lib/libc/stdio/local.h (expand / switch to unified diff)

--- src/lib/libc/stdio/local.h 2009/09/24 20:38:53 1.21
+++ src/lib/libc/stdio/local.h 2009/12/01 00:03:53 1.22
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: local.h,v 1.21 2009/09/24 20:38:53 roy Exp $ */ 1/* $NetBSD: local.h,v 1.22 2009/12/01 00:03:53 roy Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1990, 1993 4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Chris Torek. 8 * Chris Torek.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -65,28 +65,26 @@ extern int __svfscanf_unlocked __P((FILE @@ -65,28 +65,26 @@ extern int __svfscanf_unlocked __P((FILE
65 _BSD_VA_LIST_)) 65 _BSD_VA_LIST_))
66 __attribute__((__format__(__scanf__, 2, 0))); 66 __attribute__((__format__(__scanf__, 2, 0)));
67extern int __vfprintf_unlocked __P((FILE * __restrict, const char * __restrict, 67extern int __vfprintf_unlocked __P((FILE * __restrict, const char * __restrict,
68 _BSD_VA_LIST_)); 68 _BSD_VA_LIST_));
69 69
70 70
71extern int __sdidinit; 71extern int __sdidinit;
72 72
73extern int __gettemp __P((char *, int *, int)); 73extern int __gettemp __P((char *, int *, int));
74 74
75extern wint_t __fgetwc_unlock __P((FILE *)); 75extern wint_t __fgetwc_unlock __P((FILE *));
76extern wint_t __fputwc_unlock __P((wchar_t, FILE *)); 76extern wint_t __fputwc_unlock __P((wchar_t, FILE *));
77 77
78extern ssize_t __getdelim __P((char ** __restrict, size_t * __restrict, int, 
79 FILE * __restrict)); 
80extern char *__fgetstr __P((FILE * __restrict, size_t * __restrict, int)); 78extern char *__fgetstr __P((FILE * __restrict, size_t * __restrict, int));
81extern int __vfwprintf_unlocked __P((FILE *, const wchar_t *, 79extern int __vfwprintf_unlocked __P((FILE *, const wchar_t *,
82 _BSD_VA_LIST_)); 80 _BSD_VA_LIST_));
83extern int __vfwscanf_unlocked __P((FILE * __restrict, 81extern int __vfwscanf_unlocked __P((FILE * __restrict,
84 const wchar_t * __restrict, _BSD_VA_LIST_)); 82 const wchar_t * __restrict, _BSD_VA_LIST_));
85 83
86/* 84/*
87 * Return true iff the given FILE cannot be written now. 85 * Return true iff the given FILE cannot be written now.
88 */ 86 */
89#define cantwrite(fp) \ 87#define cantwrite(fp) \
90 ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \ 88 ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \
91 __swsetup(fp)) 89 __swsetup(fp))
92 90