2626#include <stdlib.h>
2727#include <stdarg.h>
2828#include <string.h>
29+ #include <stdint.h>
2930
3031#include "strbuf.h"
3132
@@ -38,22 +39,22 @@ static void die(const char *fmt, ...)
3839 va_end (arg );
3940 fprintf (stderr , "\n" );
4041
41- exit ( -1 );
42+ abort ( );
4243}
4344
44- void strbuf_init (strbuf_t * s , int len )
45+ void strbuf_init (strbuf_t * s , size_t len )
4546{
46- int size ;
47+ size_t size ;
4748
48- if (len <= 0 )
49+ if (! len )
4950 size = STRBUF_DEFAULT_SIZE ;
5051 else
51- size = len + 1 ; /* \0 terminator */
52-
52+ size = len + 1 ;
53+ if (size < len )
54+ die ("Overflow, len: %zu" , len );
5355 s -> buf = NULL ;
5456 s -> size = size ;
5557 s -> length = 0 ;
56- s -> increment = STRBUF_DEFAULT_INCREMENT ;
5758 s -> dynamic = 0 ;
5859 s -> reallocs = 0 ;
5960 s -> debug = 0 ;
@@ -65,7 +66,7 @@ void strbuf_init(strbuf_t *s, int len)
6566 strbuf_ensure_null (s );
6667}
6768
68- strbuf_t * strbuf_new (int len )
69+ strbuf_t * strbuf_new (size_t len )
6970{
7071 strbuf_t * s ;
7172
@@ -81,20 +82,10 @@ strbuf_t *strbuf_new(int len)
8182 return s ;
8283}
8384
84- void strbuf_set_increment (strbuf_t * s , int increment )
85- {
86- /* Increment > 0: Linear buffer growth rate
87- * Increment < -1: Exponential buffer growth rate */
88- if (increment == 0 || increment == -1 )
89- die ("BUG: Invalid string increment" );
90-
91- s -> increment = increment ;
92- }
93-
9485static inline void debug_stats (strbuf_t * s )
9586{
9687 if (s -> debug ) {
97- fprintf (stderr , "strbuf(%lx) reallocs: %d, length: %d , size: %d \n" ,
88+ fprintf (stderr , "strbuf(%lx) reallocs: %d, length: %zd , size: %zd \n" ,
9889 (long )s , s -> reallocs , s -> length , s -> size );
9990 }
10091}
@@ -113,7 +104,7 @@ void strbuf_free(strbuf_t *s)
113104 free (s );
114105}
115106
116- char * strbuf_free_to_string (strbuf_t * s , int * len )
107+ char * strbuf_free_to_string (strbuf_t * s , size_t * len )
117108{
118109 char * buf ;
119110
@@ -131,57 +122,63 @@ char *strbuf_free_to_string(strbuf_t *s, int *len)
131122 return buf ;
132123}
133124
134- static int calculate_new_size (strbuf_t * s , int len )
125+ static size_t calculate_new_size (strbuf_t * s , size_t len )
135126{
136- int reqsize , newsize ;
127+ size_t reqsize , newsize ;
137128
138129 if (len <= 0 )
139130 die ("BUG: Invalid strbuf length requested" );
140131
141132 /* Ensure there is room for optional NULL termination */
142133 reqsize = len + 1 ;
134+ if (reqsize < len )
135+ die ("Overflow, len: %zu" , len );
143136
144137 /* If the user has requested to shrink the buffer, do it exactly */
145138 if (s -> size > reqsize )
146139 return reqsize ;
147140
148141 newsize = s -> size ;
149- if (s -> increment < 0 ) {
142+ if (reqsize >= SIZE_MAX / 2 ) {
143+ newsize = reqsize ;
144+ } else {
150145 /* Exponential sizing */
151146 while (newsize < reqsize )
152- newsize *= - s -> increment ;
153- } else if (s -> increment != 0 ) {
154- /* Linear sizing */
155- newsize = ((newsize + s -> increment - 1 ) / s -> increment ) * s -> increment ;
147+ newsize *= 2 ;
156148 }
157149
150+ if (newsize < reqsize )
151+ die ("BUG: strbuf length would overflow, len: %zu" , len );
152+
153+
158154 return newsize ;
159155}
160156
161157
162158/* Ensure strbuf can handle a string length bytes long (ignoring NULL
163159 * optional termination). */
164- void strbuf_resize (strbuf_t * s , int len )
160+ void strbuf_resize (strbuf_t * s , size_t len )
165161{
166- int newsize ;
162+ size_t newsize ;
167163
168164 newsize = calculate_new_size (s , len );
169165
170166 if (s -> debug > 1 ) {
171- fprintf (stderr , "strbuf(%lx) resize: %d => %d \n" ,
167+ fprintf (stderr , "strbuf(%lx) resize: %zd => %zd \n" ,
172168 (long )s , s -> size , newsize );
173169 }
174170
175171 s -> size = newsize ;
176172 s -> buf = realloc (s -> buf , s -> size );
177173 if (!s -> buf )
178- die ("Out of memory" );
174+ die ("Out of memory, len: %zu" , len );
179175 s -> reallocs ++ ;
180176}
181177
182178void strbuf_append_string (strbuf_t * s , const char * str )
183179{
184- int space , i ;
180+ int i ;
181+ size_t space ;
185182
186183 space = strbuf_empty_length (s );
187184
@@ -197,55 +194,6 @@ void strbuf_append_string(strbuf_t *s, const char *str)
197194 }
198195}
199196
200- /* strbuf_append_fmt() should only be used when an upper bound
201- * is known for the output string. */
202- void strbuf_append_fmt (strbuf_t * s , int len , const char * fmt , ...)
203- {
204- va_list arg ;
205- int fmt_len ;
206-
207- strbuf_ensure_empty_length (s , len );
208-
209- va_start (arg , fmt );
210- fmt_len = vsnprintf (s -> buf + s -> length , len , fmt , arg );
211- va_end (arg );
212-
213- if (fmt_len < 0 )
214- die ("BUG: Unable to convert number" ); /* This should never happen.. */
215-
216- s -> length += fmt_len ;
217- }
218-
219- /* strbuf_append_fmt_retry() can be used when the there is no known
220- * upper bound for the output string. */
221- void strbuf_append_fmt_retry (strbuf_t * s , const char * fmt , ...)
222- {
223- va_list arg ;
224- int fmt_len , try ;
225- int empty_len ;
226-
227- /* If the first attempt to append fails, resize the buffer appropriately
228- * and try again */
229- for (try = 0 ; ; try ++ ) {
230- va_start (arg , fmt );
231- /* Append the new formatted string */
232- /* fmt_len is the length of the string required, excluding the
233- * trailing NULL */
234- empty_len = strbuf_empty_length (s );
235- /* Add 1 since there is also space to store the terminating NULL. */
236- fmt_len = vsnprintf (s -> buf + s -> length , empty_len + 1 , fmt , arg );
237- va_end (arg );
238-
239- if (fmt_len <= empty_len )
240- break ; /* SUCCESS */
241- if (try > 0 )
242- die ("BUG: length of formatted string changed" );
243-
244- strbuf_resize (s , s -> length + fmt_len );
245- }
246-
247- s -> length += fmt_len ;
248- }
249197
250198/* vi:ai et sw=4 ts=4:
251199 */
0 commit comments