File: | compat/obstack.c |
Location: | line 175, column 5 |
Description: | Access to field 'limit' results in a dereference of a null pointer (loaded from variable 'chunk') |
1 | /* obstack.c - subroutines used implicitly by object stack macros | |||
2 | Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, | |||
3 | 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. | |||
4 | This file is part of the GNU C Library. | |||
5 | ||||
6 | The GNU C Library is free software; you can redistribute it and/or | |||
7 | modify it under the terms of the GNU Lesser General Public | |||
8 | License as published by the Free Software Foundation; either | |||
9 | version 2.1 of the License, or (at your option) any later version. | |||
10 | ||||
11 | The GNU C Library is distributed in the hope that it will be useful, | |||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
14 | Lesser General Public License for more details. | |||
15 | ||||
16 | You should have received a copy of the GNU Lesser General Public | |||
17 | License along with the GNU C Library; if not, write to the Free | |||
18 | Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |||
19 | Boston, MA 02110-1301, USA. */ | |||
20 | ||||
21 | #include "git-compat-util.h" | |||
22 | #include <gettext.h> | |||
23 | #include "obstack.h" | |||
24 | ||||
25 | /* NOTE BEFORE MODIFYING THIS FILE: This version number must be | |||
26 | incremented whenever callers compiled using an old obstack.h can no | |||
27 | longer properly call the functions in this obstack.c. */ | |||
28 | #define OBSTACK_INTERFACE_VERSION1 1 | |||
29 | ||||
30 | /* Comment out all this code if we are using the GNU C Library, and are not | |||
31 | actually compiling the library itself, and the installed library | |||
32 | supports the same library interface we do. This code is part of the GNU | |||
33 | C Library, but also included in many other GNU distributions. Compiling | |||
34 | and linking in this code is a waste when using the GNU C library | |||
35 | (especially if it is a shared library). Rather than having every GNU | |||
36 | program understand `configure --with-gnu-libc' and omit the object | |||
37 | files, it is simpler to just do this in the source for each such file. */ | |||
38 | ||||
39 | #include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */ | |||
40 | #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 | |||
41 | # include <gnu-versions.h> | |||
42 | # if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION1 | |||
43 | # define ELIDE_CODE | |||
44 | # endif | |||
45 | #endif | |||
46 | ||||
47 | #include <stddef.h> | |||
48 | ||||
49 | #ifndef ELIDE_CODE | |||
50 | ||||
51 | ||||
52 | # if HAVE_INTTYPES_H | |||
53 | # include <inttypes.h> | |||
54 | # endif | |||
55 | # if HAVE_STDINT_H || defined _LIBC | |||
56 | # include <stdint.h> | |||
57 | # endif | |||
58 | ||||
59 | /* Determine default alignment. */ | |||
60 | union fooround | |||
61 | { | |||
62 | uintmax_t i; | |||
63 | long double d; | |||
64 | void *p; | |||
65 | }; | |||
66 | struct fooalign | |||
67 | { | |||
68 | char c; | |||
69 | union fooround u; | |||
70 | }; | |||
71 | /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. | |||
72 | But in fact it might be less smart and round addresses to as much as | |||
73 | DEFAULT_ROUNDING. So we prepare for it to do that. */ | |||
74 | enum | |||
75 | { | |||
76 | DEFAULT_ALIGNMENT = offsetof (struct fooalign, u)__builtin_offsetof(struct fooalign, u), | |||
77 | DEFAULT_ROUNDING = sizeof (union fooround) | |||
78 | }; | |||
79 | ||||
80 | /* When we copy a long block of data, this is the unit to do it with. | |||
81 | On some machines, copying successive ints does not work; | |||
82 | in such a case, redefine COPYING_UNIT to `long' (if that works) | |||
83 | or `char' as a last resort. */ | |||
84 | # ifndef COPYING_UNITint | |||
85 | # define COPYING_UNITint int | |||
86 | # endif | |||
87 | ||||
88 | ||||
89 | /* The functions allocating more room by calling `obstack_chunk_alloc' | |||
90 | jump to the handler pointed to by `obstack_alloc_failed_handler'. | |||
91 | This can be set to a user defined function which should either | |||
92 | abort gracefully or use longjump - but shouldn't return. This | |||
93 | variable by default points to the internal function | |||
94 | `print_and_abort'. */ | |||
95 | static void print_and_abort (void); | |||
96 | void (*obstack_alloc_failed_handler) (void) = print_and_abort; | |||
97 | ||||
98 | # ifdef _LIBC | |||
99 | # if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) | |||
100 | /* A looong time ago (before 1994, anyway; we're not sure) this global variable | |||
101 | was used by non-GNU-C macros to avoid multiple evaluation. The GNU C | |||
102 | library still exports it because somebody might use it. */ | |||
103 | struct obstack *_obstack_compat; | |||
104 | compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0); | |||
105 | # endif | |||
106 | # endif | |||
107 | ||||
108 | /* Define a macro that either calls functions with the traditional malloc/free | |||
109 | calling interface, or calls functions with the mmalloc/mfree interface | |||
110 | (that adds an extra first argument), based on the state of use_extra_arg. | |||
111 | For free, do not use ?:, since some compilers, like the MIPS compilers, | |||
112 | do not allow (expr) ? void : void. */ | |||
113 | ||||
114 | # define CALL_CHUNKFUN(h, size)(((h) -> use_extra_arg) ? (*(h)->chunkfun) ((h)->extra_arg , (size)) : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun ) ((size))) \ | |||
115 | (((h) -> use_extra_arg) \ | |||
116 | ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ | |||
117 | : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) | |||
118 | ||||
119 | # define CALL_FREEFUN(h, old_chunk)do { if ((h) -> use_extra_arg) (*(h)->freefun) ((h)-> extra_arg, (old_chunk)); else (*(void (*) (void *)) (h)->freefun ) ((old_chunk)); } while (0) \ | |||
120 | do { \ | |||
121 | if ((h) -> use_extra_arg) \ | |||
122 | (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ | |||
123 | else \ | |||
124 | (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ | |||
125 | } while (0) | |||
126 | ||||
127 | ||||
128 | /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). | |||
129 | Objects start on multiples of ALIGNMENT (0 means use default). | |||
130 | CHUNKFUN is the function to use to allocate chunks, | |||
131 | and FREEFUN the function to free them. | |||
132 | ||||
133 | Return nonzero if successful, calls obstack_alloc_failed_handler if | |||
134 | allocation fails. */ | |||
135 | ||||
136 | int | |||
137 | _obstack_begin (struct obstack *h, | |||
138 | int size, int alignment, | |||
139 | void *(*chunkfun) (long), | |||
140 | void (*freefun) (void *)) | |||
141 | { | |||
142 | register struct _obstack_chunk *chunk; /* points to new chunk */ | |||
143 | ||||
144 | if (alignment == 0) | |||
| ||||
145 | alignment = DEFAULT_ALIGNMENT; | |||
146 | if (size == 0) | |||
147 | /* Default size is what GNU malloc can fit in a 4096-byte block. */ | |||
148 | { | |||
149 | /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. | |||
150 | Use the values for range checking, because if range checking is off, | |||
151 | the extra bytes won't be missed terribly, but if range checking is on | |||
152 | and we used a larger request, a whole extra 4096 bytes would be | |||
153 | allocated. | |||
154 | ||||
155 | These number are irrelevant to the new GNU malloc. I suspect it is | |||
156 | less sensitive to the size of the request. */ | |||
157 | int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) | |||
158 | + 4 + DEFAULT_ROUNDING - 1) | |||
159 | & ~(DEFAULT_ROUNDING - 1)); | |||
160 | size = 4096 - extra; | |||
161 | } | |||
162 | ||||
163 | h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; | |||
164 | h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; | |||
165 | h->chunk_size = size; | |||
166 | h->alignment_mask = alignment - 1; | |||
167 | h->use_extra_arg = 0; | |||
168 | ||||
169 | chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size)(((h) -> use_extra_arg) ? (*(h)->chunkfun) ((h)->extra_arg , (h -> chunk_size)) : (*(struct _obstack_chunk *(*) (long )) (h)->chunkfun) ((h -> chunk_size))); | |||
170 | if (!chunk) | |||
171 | (*obstack_alloc_failed_handler) (); | |||
172 | h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,((sizeof (long int) < sizeof (void *) ? ((char *) chunk) : (char *) 0) + (((chunk->contents) - (sizeof (long int) < sizeof (void *) ? ((char *) chunk) : (char *) 0) + (alignment - 1)) & ~(alignment - 1))) | |||
173 | alignment - 1)((sizeof (long int) < sizeof (void *) ? ((char *) chunk) : (char *) 0) + (((chunk->contents) - (sizeof (long int) < sizeof (void *) ? ((char *) chunk) : (char *) 0) + (alignment - 1)) & ~(alignment - 1))); | |||
174 | h->chunk_limit = chunk->limit | |||
175 | = (char *) chunk + h->chunk_size; | |||
| ||||
176 | chunk->prev = NULL((void*)0); | |||
177 | /* The initial chunk now contains no empty object. */ | |||
178 | h->maybe_empty_object = 0; | |||
179 | h->alloc_failed = 0; | |||
180 | return 1; | |||
181 | } | |||
182 | ||||
183 | int | |||
184 | _obstack_begin_1 (struct obstack *h, int size, int alignment, | |||
185 | void *(*chunkfun) (void *, long), | |||
186 | void (*freefun) (void *, void *), | |||
187 | void *arg) | |||
188 | { | |||
189 | register struct _obstack_chunk *chunk; /* points to new chunk */ | |||
190 | ||||
191 | if (alignment == 0) | |||
192 | alignment = DEFAULT_ALIGNMENT; | |||
193 | if (size == 0) | |||
194 | /* Default size is what GNU malloc can fit in a 4096-byte block. */ | |||
195 | { | |||
196 | /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. | |||
197 | Use the values for range checking, because if range checking is off, | |||
198 | the extra bytes won't be missed terribly, but if range checking is on | |||
199 | and we used a larger request, a whole extra 4096 bytes would be | |||
200 | allocated. | |||
201 | ||||
202 | These number are irrelevant to the new GNU malloc. I suspect it is | |||
203 | less sensitive to the size of the request. */ | |||
204 | int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) | |||
205 | + 4 + DEFAULT_ROUNDING - 1) | |||
206 | & ~(DEFAULT_ROUNDING - 1)); | |||
207 | size = 4096 - extra; | |||
208 | } | |||
209 | ||||
210 | h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; | |||
211 | h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; | |||
212 | h->chunk_size = size; | |||
213 | h->alignment_mask = alignment - 1; | |||
214 | h->extra_arg = arg; | |||
215 | h->use_extra_arg = 1; | |||
216 | ||||
217 | chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size)(((h) -> use_extra_arg) ? (*(h)->chunkfun) ((h)->extra_arg , (h -> chunk_size)) : (*(struct _obstack_chunk *(*) (long )) (h)->chunkfun) ((h -> chunk_size))); | |||
218 | if (!chunk) | |||
219 | (*obstack_alloc_failed_handler) (); | |||
220 | h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,((sizeof (long int) < sizeof (void *) ? ((char *) chunk) : (char *) 0) + (((chunk->contents) - (sizeof (long int) < sizeof (void *) ? ((char *) chunk) : (char *) 0) + (alignment - 1)) & ~(alignment - 1))) | |||
221 | alignment - 1)((sizeof (long int) < sizeof (void *) ? ((char *) chunk) : (char *) 0) + (((chunk->contents) - (sizeof (long int) < sizeof (void *) ? ((char *) chunk) : (char *) 0) + (alignment - 1)) & ~(alignment - 1))); | |||
222 | h->chunk_limit = chunk->limit | |||
223 | = (char *) chunk + h->chunk_size; | |||
224 | chunk->prev = NULL((void*)0); | |||
225 | /* The initial chunk now contains no empty object. */ | |||
226 | h->maybe_empty_object = 0; | |||
227 | h->alloc_failed = 0; | |||
228 | return 1; | |||
229 | } | |||
230 | ||||
231 | /* Allocate a new current chunk for the obstack *H | |||
232 | on the assumption that LENGTH bytes need to be added | |||
233 | to the current object, or a new object of length LENGTH allocated. | |||
234 | Copies any partial object from the end of the old chunk | |||
235 | to the beginning of the new one. */ | |||
236 | ||||
237 | void | |||
238 | _obstack_newchunk (struct obstack *h, int length) | |||
239 | { | |||
240 | register struct _obstack_chunk *old_chunk = h->chunk; | |||
241 | register struct _obstack_chunk *new_chunk; | |||
242 | register long new_size; | |||
243 | register long obj_size = h->next_free - h->object_base; | |||
244 | register long i; | |||
245 | long already; | |||
246 | char *object_base; | |||
247 | ||||
248 | /* Compute size for new chunk. */ | |||
249 | new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100; | |||
250 | if (new_size < h->chunk_size) | |||
251 | new_size = h->chunk_size; | |||
252 | ||||
253 | /* Allocate and initialize the new chunk. */ | |||
254 | new_chunk = CALL_CHUNKFUN (h, new_size)(((h) -> use_extra_arg) ? (*(h)->chunkfun) ((h)->extra_arg , (new_size)) : (*(struct _obstack_chunk *(*) (long)) (h)-> chunkfun) ((new_size))); | |||
255 | if (!new_chunk) | |||
256 | (*obstack_alloc_failed_handler) (); | |||
257 | h->chunk = new_chunk; | |||
258 | new_chunk->prev = old_chunk; | |||
259 | new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; | |||
260 | ||||
261 | /* Compute an aligned object_base in the new chunk */ | |||
262 | object_base = | |||
263 | __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask)((sizeof (long int) < sizeof (void *) ? ((char *) new_chunk ) : (char *) 0) + (((new_chunk->contents) - (sizeof (long int ) < sizeof (void *) ? ((char *) new_chunk) : (char *) 0) + (h->alignment_mask)) & ~(h->alignment_mask))); | |||
264 | ||||
265 | /* Move the existing object to the new chunk. | |||
266 | Word at a time is fast and is safe if the object | |||
267 | is sufficiently aligned. */ | |||
268 | if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) | |||
269 | { | |||
270 | for (i = obj_size / sizeof (COPYING_UNITint) - 1; | |||
271 | i >= 0; i--) | |||
272 | ((COPYING_UNITint *)object_base)[i] | |||
273 | = ((COPYING_UNITint *)h->object_base)[i]; | |||
274 | /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT, | |||
275 | but that can cross a page boundary on a machine | |||
276 | which does not do strict alignment for COPYING_UNITS. */ | |||
277 | already = obj_size / sizeof (COPYING_UNITint) * sizeof (COPYING_UNITint); | |||
278 | } | |||
279 | else | |||
280 | already = 0; | |||
281 | /* Copy remaining bytes one by one. */ | |||
282 | for (i = already; i < obj_size; i++) | |||
283 | object_base[i] = h->object_base[i]; | |||
284 | ||||
285 | /* If the object just copied was the only data in OLD_CHUNK, | |||
286 | free that chunk and remove it from the chain. | |||
287 | But not if that chunk might contain an empty object. */ | |||
288 | if (! h->maybe_empty_object | |||
289 | && (h->object_base | |||
290 | == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,((sizeof (long int) < sizeof (void *) ? ((char *) old_chunk ) : (char *) 0) + (((old_chunk->contents) - (sizeof (long int ) < sizeof (void *) ? ((char *) old_chunk) : (char *) 0) + (h->alignment_mask)) & ~(h->alignment_mask))) | |||
291 | h->alignment_mask)((sizeof (long int) < sizeof (void *) ? ((char *) old_chunk ) : (char *) 0) + (((old_chunk->contents) - (sizeof (long int ) < sizeof (void *) ? ((char *) old_chunk) : (char *) 0) + (h->alignment_mask)) & ~(h->alignment_mask))))) | |||
292 | { | |||
293 | new_chunk->prev = old_chunk->prev; | |||
294 | CALL_FREEFUN (h, old_chunk)do { if ((h) -> use_extra_arg) (*(h)->freefun) ((h)-> extra_arg, (old_chunk)); else (*(void (*) (void *)) (h)->freefun ) ((old_chunk)); } while (0); | |||
295 | } | |||
296 | ||||
297 | h->object_base = object_base; | |||
298 | h->next_free = h->object_base + obj_size; | |||
299 | /* The new chunk certainly contains no empty object yet. */ | |||
300 | h->maybe_empty_object = 0; | |||
301 | } | |||
302 | # ifdef _LIBC | |||
303 | libc_hidden_def (_obstack_newchunk) | |||
304 | # endif | |||
305 | ||||
306 | /* Return nonzero if object OBJ has been allocated from obstack H. | |||
307 | This is here for debugging. | |||
308 | If you use it in a program, you are probably losing. */ | |||
309 | ||||
310 | /* Suppress -Wmissing-prototypes warning. We don't want to declare this in | |||
311 | obstack.h because it is just for debugging. */ | |||
312 | int _obstack_allocated_p (struct obstack *h, void *obj); | |||
313 | ||||
314 | int | |||
315 | _obstack_allocated_p (struct obstack *h, void *obj) | |||
316 | { | |||
317 | register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ | |||
318 | register struct _obstack_chunk *plp; /* point to previous chunk if any */ | |||
319 | ||||
320 | lp = (h)->chunk; | |||
321 | /* We use >= rather than > since the object cannot be exactly at | |||
322 | the beginning of the chunk but might be an empty object exactly | |||
323 | at the end of an adjacent chunk. */ | |||
324 | while (lp != NULL((void*)0) && ((void *) lp >= obj || (void *) (lp)->limit < obj)) | |||
325 | { | |||
326 | plp = lp->prev; | |||
327 | lp = plp; | |||
328 | } | |||
329 | return lp != NULL((void*)0); | |||
330 | } | |||
331 | ||||
332 | /* Free objects in obstack H, including OBJ and everything allocate | |||
333 | more recently than OBJ. If OBJ is zero, free everything in H. */ | |||
334 | ||||
335 | # undef obstack_free | |||
336 | ||||
337 | void | |||
338 | obstack_free (struct obstack *h, void *obj) | |||
339 | { | |||
340 | register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ | |||
341 | register struct _obstack_chunk *plp; /* point to previous chunk if any */ | |||
342 | ||||
343 | lp = h->chunk; | |||
344 | /* We use >= because there cannot be an object at the beginning of a chunk. | |||
345 | But there can be an empty object at that address | |||
346 | at the end of another chunk. */ | |||
347 | while (lp != NULL((void*)0) && ((void *) lp >= obj || (void *) (lp)->limit < obj)) | |||
348 | { | |||
349 | plp = lp->prev; | |||
350 | CALL_FREEFUN (h, lp)do { if ((h) -> use_extra_arg) (*(h)->freefun) ((h)-> extra_arg, (lp)); else (*(void (*) (void *)) (h)->freefun) ((lp)); } while (0); | |||
351 | lp = plp; | |||
352 | /* If we switch chunks, we can't tell whether the new current | |||
353 | chunk contains an empty object, so assume that it may. */ | |||
354 | h->maybe_empty_object = 1; | |||
355 | } | |||
356 | if (lp) | |||
357 | { | |||
358 | h->object_base = h->next_free = (char *) (obj); | |||
359 | h->chunk_limit = lp->limit; | |||
360 | h->chunk = lp; | |||
361 | } | |||
362 | else if (obj != NULL((void*)0)) | |||
363 | /* obj is not in any of the chunks! */ | |||
364 | abort (); | |||
365 | } | |||
366 | ||||
367 | # ifdef _LIBC | |||
368 | /* Older versions of libc used a function _obstack_free intended to be | |||
369 | called by non-GCC compilers. */ | |||
370 | strong_alias (obstack_free, _obstack_free) | |||
371 | # endif | |||
372 | ||||
373 | int | |||
374 | _obstack_memory_used (struct obstack *h) | |||
375 | { | |||
376 | register struct _obstack_chunk* lp; | |||
377 | register int nbytes = 0; | |||
378 | ||||
379 | for (lp = h->chunk; lp != NULL((void*)0); lp = lp->prev) | |||
380 | { | |||
381 | nbytes += lp->limit - (char *) lp; | |||
382 | } | |||
383 | return nbytes; | |||
384 | } | |||
385 | ||||
386 | # ifdef _LIBC | |||
387 | # include <libio/iolibio.h> | |||
388 | # endif | |||
389 | ||||
390 | # ifndef __attribute__ | |||
391 | /* This feature is available in gcc versions 2.5 and later. */ | |||
392 | # if __GNUC__4 < 2 || (__GNUC__4 == 2 && __GNUC_MINOR__2 < 5) | |||
393 | # define __attribute__(Spec) /* empty */ | |||
394 | # endif | |||
395 | # endif | |||
396 | ||||
397 | static void | |||
398 | print_and_abort (void) | |||
399 | { | |||
400 | /* Don't change any of these strings. Yes, it would be possible to add | |||
401 | the newline to the string and use fputs or so. But this must not | |||
402 | happen because the "memory exhausted" message appears in other places | |||
403 | like this and the translation should be reused instead of creating | |||
404 | a very similar string which requires a separate translation. */ | |||
405 | # ifdef _LIBC | |||
406 | (void) __fxprintf (NULL((void*)0), "%s\n", _("memory exhausted")); | |||
407 | # else | |||
408 | fprintf (stderr__stderrp, "%s\n", _("memory exhausted")); | |||
409 | # endif | |||
410 | exit (1); | |||
411 | } | |||
412 | ||||
413 | #endif /* !ELIDE_CODE */ |