mirror of
https://github.com/neovim/neovim.git
synced 2025-09-12 14:28:18 +00:00
Fix warnings: memory.c: xcalloc(): 0 size calloc: CW.
Problem : Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131) @ 148. Diagnostic : Cautionary warning. Rationale : Reported circumstance (calling calloc with requesting 0 size allocation) can occur, and it's not an issue. It's perfectly legal doing so, though result is implementation dependant. A given implementation can return NULL or a valid pointer, so that free() can be called on it later the same as if it was a real pointer. Such a pointer should not be dereferenced, though. Now, for some reason I can't explain, compiler is warning us in the case of calloc, but not in the case of malloc, which is doing the same. Resolution : Refactor memory functions to avoid using implementation dependant behaviour. Proposed code is neater to read, and it avoids calling system memory functions with size 0, thus behaving the same everywhere. Note that semantics for xmalloc/xcalloc is slightly changed: - Previously, an implementation that returns a valid pointer on malloc/calloc with 0 size, would return that pointer to xmalloc/xcalloc caller. - Currently, a regular pointer is always returned.
This commit is contained in:
@@ -78,17 +78,11 @@ static void try_to_free_memory(void)
|
|||||||
/// @return pointer to allocated space. NULL if out of memory
|
/// @return pointer to allocated space. NULL if out of memory
|
||||||
void *try_malloc(size_t size) FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1)
|
void *try_malloc(size_t size) FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1)
|
||||||
{
|
{
|
||||||
|
size = size ? size : 1;
|
||||||
void *ret = malloc(size);
|
void *ret = malloc(size);
|
||||||
|
|
||||||
if (!ret && !size) {
|
|
||||||
ret = malloc(1);
|
|
||||||
}
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
try_to_free_memory();
|
try_to_free_memory();
|
||||||
ret = malloc(size);
|
ret = malloc(size);
|
||||||
if (!ret && !size) {
|
|
||||||
ret = malloc(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -120,7 +114,6 @@ void *xmalloc(size_t size)
|
|||||||
FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1) FUNC_ATTR_NONNULL_RET
|
FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1) FUNC_ATTR_NONNULL_RET
|
||||||
{
|
{
|
||||||
void *ret = try_malloc(size);
|
void *ret = try_malloc(size);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
OUT_STR(e_outofmem);
|
OUT_STR(e_outofmem);
|
||||||
out_char('\n');
|
out_char('\n');
|
||||||
@@ -138,23 +131,16 @@ void *xmalloc(size_t size)
|
|||||||
void *xcalloc(size_t count, size_t size)
|
void *xcalloc(size_t count, size_t size)
|
||||||
FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE_PROD(1, 2) FUNC_ATTR_NONNULL_RET
|
FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE_PROD(1, 2) FUNC_ATTR_NONNULL_RET
|
||||||
{
|
{
|
||||||
void *ret = calloc(count, size);
|
void *ret = count && size ? calloc(count, size) : calloc(1, 1);
|
||||||
|
|
||||||
if (!ret && (!count || !size))
|
|
||||||
ret = calloc(1, 1);
|
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
try_to_free_memory();
|
try_to_free_memory();
|
||||||
ret = calloc(count, size);
|
ret = count && size ? calloc(count, size) : calloc(1, 1);
|
||||||
if (!ret && (!count || !size))
|
|
||||||
ret = calloc(1, 1);
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
OUT_STR(e_outofmem);
|
OUT_STR(e_outofmem);
|
||||||
out_char('\n');
|
out_char('\n');
|
||||||
preserve_exit();
|
preserve_exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,23 +152,16 @@ void *xcalloc(size_t count, size_t size)
|
|||||||
void *xrealloc(void *ptr, size_t size)
|
void *xrealloc(void *ptr, size_t size)
|
||||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALLOC_SIZE(2) FUNC_ATTR_NONNULL_RET
|
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALLOC_SIZE(2) FUNC_ATTR_NONNULL_RET
|
||||||
{
|
{
|
||||||
void *ret = realloc(ptr, size);
|
void *ret = size ? realloc(ptr, size) : realloc(ptr, 1);
|
||||||
|
|
||||||
if (!ret && !size)
|
|
||||||
ret = realloc(ptr, 1);
|
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
try_to_free_memory();
|
try_to_free_memory();
|
||||||
ret = realloc(ptr, size);
|
ret = size ? realloc(ptr, size) : realloc(ptr, 1);
|
||||||
if (!ret && !size)
|
|
||||||
ret = realloc(ptr, 1);
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
OUT_STR(e_outofmem);
|
OUT_STR(e_outofmem);
|
||||||
out_char('\n');
|
out_char('\n');
|
||||||
preserve_exit();
|
preserve_exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,14 +174,12 @@ void *xmallocz(size_t size)
|
|||||||
FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
|
FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
|
||||||
{
|
{
|
||||||
size_t total_size = size + 1;
|
size_t total_size = size + 1;
|
||||||
void *ret;
|
|
||||||
|
|
||||||
if (total_size < size) {
|
if (total_size < size) {
|
||||||
OUT_STR(_("Vim: Data too large to fit into virtual memory space\n"));
|
OUT_STR(_("Vim: Data too large to fit into virtual memory space\n"));
|
||||||
preserve_exit();
|
preserve_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = xmalloc(total_size);
|
void *ret = xmalloc(total_size);
|
||||||
((char*)ret)[size] = 0;
|
((char*)ret)[size] = 0;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
Reference in New Issue
Block a user