diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2019-06-13 01:48:30 +0300 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2019-06-13 01:48:30 +0300 |
commit | fd62683c0dc0a16a27fcfc82b43e57ef13ac9a38 (patch) | |
tree | b044064d205408582101f358ca0efe83798da98d | |
parent | e1cdae6b96865aba121fc17d37519f670691d008 (diff) | |
download | libmicrohttpd-fd62683c0dc0a16a27fcfc82b43e57ef13ac9a38.tar.gz libmicrohttpd-fd62683c0dc0a16a27fcfc82b43e57ef13ac9a38.zip |
memorypool: fixed/rewritten MHD_pool_reallocate()
-rw-r--r-- | src/microhttpd/memorypool.c | 72 |
1 files changed, 35 insertions, 37 deletions
diff --git a/src/microhttpd/memorypool.c b/src/microhttpd/memorypool.c index 3746eb71..4a890967 100644 --- a/src/microhttpd/memorypool.c +++ b/src/microhttpd/memorypool.c | |||
@@ -257,55 +257,53 @@ MHD_pool_reallocate (struct MemoryPool *pool, | |||
257 | size_t old_size, | 257 | size_t old_size, |
258 | size_t new_size) | 258 | size_t new_size) |
259 | { | 259 | { |
260 | void *ret; | ||
261 | size_t asize; | 260 | size_t asize; |
261 | uint8_t *new_blc; | ||
262 | 262 | ||
263 | mhd_assert (pool->end >= pool->pos); | 263 | mhd_assert (pool->end >= pool->pos); |
264 | mhd_assert (pool->size >= pool->end - pool->pos); | 264 | mhd_assert (pool->size >= pool->end - pool->pos); |
265 | mhd_assert (old != NULL || old_size == 0); | 265 | mhd_assert (old != NULL || old_size == 0); |
266 | mhd_assert (old == NULL || pool->memory <= (uint8_t*)old); | 266 | mhd_assert (old == NULL || pool->memory <= (uint8_t*)old); |
267 | mhd_assert (old == NULL || pool->memory + pool->size >= (uint8_t*)old + old_size); | 267 | mhd_assert (old == NULL || pool->memory + pool->size >= (uint8_t*)old + old_size); |
268 | asize = ROUND_TO_ALIGN (new_size); | 268 | /* Blocks "from the end" must not be reallocated */ |
269 | if ( (0 == asize) && | 269 | mhd_assert (old == NULL || pool->memory + pool->pos > (uint8_t*)old); |
270 | (0 != new_size) ) | 270 | |
271 | return NULL; /* new_size too close to SIZE_MAX */ | 271 | if (pool->memory + new_size + 2 * ALIGN_SIZE< pool->memory) |
272 | if ( (pool->end < old_size) || | 272 | return NULL; /* Value wrap, too large new_size. */ |
273 | (pool->end < asize) ) | 273 | |
274 | return NULL; /* unsatisfiable or bogus request */ | 274 | if (0 != old_size) |
275 | 275 | { /* Need to relocate data */ | |
276 | if ( (pool->pos >= old_size) && | 276 | const size_t old_offset = (uint8_t*)old - pool->memory; |
277 | (&pool->memory[pool->pos - old_size] == old) ) | 277 | |
278 | { | 278 | if (pool->pos == ROUND_TO_ALIGN (old_offset + old_size)) |
279 | /* was the previous allocation - optimize! */ | 279 | { /* "old" block is the last allocated block */ |
280 | if (pool->pos + asize - old_size <= pool->end) | 280 | const size_t new_apos = ROUND_TO_ALIGN (old_offset + new_size); |
281 | { | 281 | if (new_apos > pool->end) |
282 | /* fits */ | 282 | return NULL; /* No space */ |
283 | pool->pos += asize - old_size; | 283 | |
284 | if (asize < old_size) /* shrinking - zero again! */ | 284 | pool->pos = new_apos; |
285 | memset (&pool->memory[pool->pos], | 285 | /* Zero-out unused part if shrinking */ |
286 | 0, | 286 | if (old_size > new_size) |
287 | old_size - asize); | 287 | memset (old + new_size, 0, old_size - new_size); |
288 | return old; | 288 | return old; |
289 | } | 289 | } |
290 | /* does not fit */ | ||
291 | return NULL; | ||
292 | } | 290 | } |
293 | if (asize <= old_size) | 291 | /* Need to allocate new block */ |
294 | return old; /* cannot shrink, no need to move */ | 292 | asize = ROUND_TO_ALIGN (new_size); |
295 | if ((pool->pos + asize >= pool->pos) && | 293 | if (asize > pool->end - pool->pos) |
296 | (pool->pos + asize <= pool->end)) | 294 | return NULL; /* No space */ |
295 | |||
296 | new_blc = pool->memory + pool->pos; | ||
297 | pool->pos += asize; | ||
298 | |||
299 | if (0 != old_size) | ||
297 | { | 300 | { |
298 | /* fits */ | 301 | /* Move data no new block, old block remains allocated */ |
299 | ret = &pool->memory[pool->pos]; | 302 | memcpy (new_blc, old, old_size); |
300 | if (0 != old_size) | 303 | /* Zero-out old block */ |
301 | memmove (ret, | 304 | memset (old, 0, old_size); |
302 | old, | ||
303 | old_size); | ||
304 | pool->pos += asize; | ||
305 | return ret; | ||
306 | } | 305 | } |
307 | /* does not fit */ | 306 | return new_blc; |
308 | return NULL; | ||
309 | } | 307 | } |
310 | 308 | ||
311 | 309 | ||