b851916d76
This primarily fixes allocated memory overrun due to invalidly calculated limit of the chunk. The function here allocates chunk of size that includes required header. The error was that size of the chunk was invalidly again added when limit was being calculated. This was causing memory overrun and issues especially with object growing (reallocation). The secondary fix here is to the algorithm that rounds the required size to the multiple of chunk size. In short chunk size must be reduced by one to get the correct mask. The condition that was generating the mask was also invalid because it must perform shift with at most one less than number of bits (not bytes).
113 lines
3.6 KiB
C
113 lines
3.6 KiB
C
/****************************************************************************
|
|
* libs/libc/obstack/lib_obstack_make_room.c
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <obstack.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <sys/param.h>
|
|
#include <syslog.h>
|
|
#include "lib_obstack_malloc.h"
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: obstack_make_room
|
|
*
|
|
* Description:
|
|
* This is non-standard function that is probably available only on NuttX!
|
|
* Make sure that there is room in the buffer to fit object with given
|
|
* size. The allocation performed is in multiples of chunk_size specified
|
|
* for the obstack.
|
|
*
|
|
* Input Parameters:
|
|
* h: pointer to the handle where room should be made
|
|
* size: number of bytes to be free for growth
|
|
*
|
|
* Assumptions/Limitations:
|
|
* The obstack's chunk_size is rounded up to be power of two. This helps to
|
|
* eliminate division that might not be implemented in the HW and thus
|
|
* inefficient.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void obstack_make_room(FAR struct obstack *h, size_t size)
|
|
{
|
|
unsigned i;
|
|
size_t mask;
|
|
|
|
DEBUGASSERT(h);
|
|
|
|
if (obstack_room(h) >= size)
|
|
{
|
|
return; /* No need to allocate anything */
|
|
}
|
|
|
|
size_t object_size = obstack_object_size(h);
|
|
|
|
size += object_size + sizeof(struct _obstack_chunk);
|
|
|
|
/* Note: this is rounding up to the multiple of chunk size that is rounded
|
|
* up to the power of two.
|
|
*/
|
|
|
|
DEBUGASSERT(h->chunk_size > 0);
|
|
mask = h->chunk_size - 1;
|
|
|
|
for (i = 1; i < sizeof(size_t) * 8; i <<= 1)
|
|
{
|
|
mask |= mask >> i;
|
|
}
|
|
|
|
size = (size + mask) & ~mask;
|
|
|
|
if (h->chunk == NULL ||
|
|
h->object_base != (FAR char *)h->chunk + sizeof(struct _obstack_chunk))
|
|
{
|
|
/* Allocate new chunk if there is something in the chunk already or if
|
|
* there is no chunk yet.
|
|
*/
|
|
|
|
FAR struct _obstack_chunk *prev = h->chunk;
|
|
h->chunk = lib_obstack_malloc(size);
|
|
h->chunk->prev = prev;
|
|
|
|
/* Move growing object to the new chunk */
|
|
|
|
memcpy((FAR char *)h->chunk + sizeof(struct _obstack_chunk),
|
|
h->object_base, object_size);
|
|
}
|
|
|
|
else
|
|
{
|
|
h->chunk = lib_obstack_realloc(h->chunk, size);
|
|
}
|
|
|
|
h->chunk->limit = (FAR char *)h->chunk + size;
|
|
h->object_base = (FAR char *)h->chunk + sizeof(struct _obstack_chunk);
|
|
h->next_free = h->object_base + object_size;
|
|
}
|