aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2019-05-22 00:10:35 +0200
committerJustin M. Keyes <justinkz@gmail.com>2019-05-25 10:01:17 +0200
commita9d7ec4587d8eb20f12ebecc427ad818fb0e4971 (patch)
tree4a3ec8787e9dae501ea2c1430c13c174f289ac4b
parent4769deb36a54c3b2a4a2d2addb2937c1aa7dd629 (diff)
downloadrneovim-a9d7ec4587d8eb20f12ebecc427ad818fb0e4971.tar.gz
rneovim-a9d7ec4587d8eb20f12ebecc427ad818fb0e4971.tar.bz2
rneovim-a9d7ec4587d8eb20f12ebecc427ad818fb0e4971.zip
refactor: introduce XFREE_CLEAR()
Unfortunately we cannot indiscriminately replace xfree() with XFREE_CLEAR(), because comparing pointers after freeing them is a common pattern. Example in `tv_list_remove_items()`: xfree(li); if (li == item2) { break; } Instead we can do it selectively/explicitly. ref #1375
-rw-r--r--src/nvim/lib/kbtree.h14
-rw-r--r--src/nvim/lib/khash.h2
-rw-r--r--src/nvim/lib/klist.h6
-rw-r--r--src/nvim/lib/kvec.h6
-rw-r--r--src/nvim/lib/ringbuf.h4
-rw-r--r--src/nvim/memory.c2
-rw-r--r--src/nvim/memory.h11
-rw-r--r--test/functional/autocmd/autocmd_spec.lua8
8 files changed, 33 insertions, 20 deletions
diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h
index 704aa26010..33aeff1d89 100644
--- a/src/nvim/lib/kbtree.h
+++ b/src/nvim/lib/kbtree.h
@@ -72,7 +72,7 @@
*top++ = (b)->root; \
while (top != stack) { \
x = *--top; \
- if (x->is_internal == 0) { xfree(x); continue; } \
+ if (x->is_internal == 0) { XFREE_CLEAR(x); continue; } \
for (i = 0; i <= x->n; ++i) \
if (__KB_PTR(b, x)[i]) { \
if (top - stack == (int)max) { \
@@ -82,10 +82,10 @@
} \
*top++ = __KB_PTR(b, x)[i]; \
} \
- xfree(x); \
+ XFREE_CLEAR(x); \
} \
} \
- xfree(stack); \
+ XFREE_CLEAR(stack); \
} while (0)
#define __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \
@@ -253,7 +253,7 @@
memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \
memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, x)[i + 2], (unsigned int)(x->n - i - 1) * sizeof(void*)); \
--x->n; \
- xfree(z); \
+ XFREE_CLEAR(z); \
return __kb_delp_aux_##name(b, y, k, s); \
} \
} \
@@ -281,7 +281,7 @@
memmove(&__KB_KEY(key_t, x)[i - 1], &__KB_KEY(key_t, x)[i], (unsigned int)(x->n - i) * sizeof(key_t)); \
memmove(&__KB_PTR(b, x)[i], &__KB_PTR(b, x)[i + 1], (unsigned int)(x->n - i) * sizeof(void*)); \
--x->n; \
- xfree(xp); \
+ XFREE_CLEAR(xp); \
xp = y; \
} else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n == T - 1) { \
__KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \
@@ -291,7 +291,7 @@
memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \
memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, x)[i + 2], (unsigned int)(x->n - i - 1) * sizeof(void*)); \
--x->n; \
- xfree(y); \
+ XFREE_CLEAR(y); \
} \
} \
return __kb_delp_aux_##name(b, xp, k, s); \
@@ -306,7 +306,7 @@
--b->n_nodes; \
x = b->root; \
b->root = __KB_PTR(b, x)[0]; \
- xfree(x); \
+ XFREE_CLEAR(x); \
} \
return ret; \
} \
diff --git a/src/nvim/lib/khash.h b/src/nvim/lib/khash.h
index b2994a3159..c999511543 100644
--- a/src/nvim/lib/khash.h
+++ b/src/nvim/lib/khash.h
@@ -181,7 +181,7 @@ typedef khint_t khiter_t;
#define krealloc(P,Z) xrealloc(P,Z)
#endif
#ifndef kfree
-#define kfree(P) xfree(P)
+#define kfree(P) XFREE_CLEAR(P)
#endif
#define __ac_HASH_UPPER 0.77
diff --git a/src/nvim/lib/klist.h b/src/nvim/lib/klist.h
index 7ee100ab8c..b80f4be3c2 100644
--- a/src/nvim/lib/klist.h
+++ b/src/nvim/lib/klist.h
@@ -46,9 +46,9 @@
static inline void kmp_destroy_##name(kmp_##name##_t *mp) { \
size_t k; \
for (k = 0; k < mp->n; k++) { \
- kmpfree_f(mp->buf[k]); xfree(mp->buf[k]); \
+ kmpfree_f(mp->buf[k]); XFREE_CLEAR(mp->buf[k]); \
} \
- xfree(mp->buf); xfree(mp); \
+ XFREE_CLEAR(mp->buf); XFREE_CLEAR(mp); \
} \
static inline kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \
mp->cnt++; \
@@ -100,7 +100,7 @@
} \
kmp_free(name, kl->mp, p); \
kmp_destroy(name, kl->mp); \
- xfree(kl); \
+ XFREE_CLEAR(kl); \
} \
static inline void kl_push_##name(kl_##name##_t *kl, kltype_t d) { \
kl1_##name *q, *p = kmp_alloc(name, kl->mp); \
diff --git a/src/nvim/lib/kvec.h b/src/nvim/lib/kvec.h
index 93b2f053bc..e668b10bb9 100644
--- a/src/nvim/lib/kvec.h
+++ b/src/nvim/lib/kvec.h
@@ -58,7 +58,7 @@
}
#define kv_init(v) ((v).size = (v).capacity = 0, (v).items = 0)
-#define kv_destroy(v) xfree((v).items)
+#define kv_destroy(v) XFREE_CLEAR((v).items)
#define kv_A(v, i) ((v).items[(i)])
#define kv_pop(v) ((v).items[--(v).size])
#define kv_size(v) ((v).size)
@@ -138,7 +138,7 @@ static inline void *_memcpy_free(void *const restrict dest,
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_ALWAYS_INLINE
{
memcpy(dest, src, size);
- xfree(src);
+ XFREE_CLEAR(src);
return dest;
}
@@ -201,7 +201,7 @@ static inline void *_memcpy_free(void *const restrict dest,
#define kvi_destroy(v) \
do { \
if ((v).items != (v).init_array) { \
- xfree((v).items); \
+ XFREE_CLEAR((v).items); \
} \
} while (0)
diff --git a/src/nvim/lib/ringbuf.h b/src/nvim/lib/ringbuf.h
index e63eae70b0..cb79eaf742 100644
--- a/src/nvim/lib/ringbuf.h
+++ b/src/nvim/lib/ringbuf.h
@@ -136,14 +136,14 @@ static inline void funcprefix##_rb_free(TypeName##RingBuffer *const rb) \
RINGBUF_FORALL(rb, RBType, rbitem) { \
rbfree(rbitem); \
} \
- xfree(rb->buf); \
+ XFREE_CLEAR(rb->buf); \
} \
\
static inline void funcprefix##_rb_dealloc(TypeName##RingBuffer *const rb) \
REAL_FATTR_UNUSED; \
static inline void funcprefix##_rb_dealloc(TypeName##RingBuffer *const rb) \
{ \
- xfree(rb->buf); \
+ XFREE_CLEAR(rb->buf); \
} \
\
static inline void funcprefix##_rb_push(TypeName##RingBuffer *const rb, \
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index 4ed816b157..b8a29070ce 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -110,6 +110,8 @@ void *xmalloc(size_t size)
}
/// free() wrapper that delegates to the backing memory manager
+///
+/// @note Use XFREE_CLEAR() instead, if possible.
void xfree(void *ptr)
{
free(ptr);
diff --git a/src/nvim/memory.h b/src/nvim/memory.h
index 250ac3e08f..5b39d002c9 100644
--- a/src/nvim/memory.h
+++ b/src/nvim/memory.h
@@ -40,4 +40,15 @@ extern bool entered_free_all_mem;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "memory.h.generated.h"
#endif
+
+#define XFREE_CLEAR(ptr) \
+ do { \
+ /* Take the address to avoid double evaluation. #1375 */ \
+ void **ptr_ = (void **)&(ptr); \
+ xfree(*ptr_); \
+ /* coverity[dead-store] */ \
+ *ptr_ = NULL; \
+ (void)(*ptr_); \
+ } while (0)
+
#endif // NVIM_MEMORY_H
diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua
index 337c5442ef..1eeaa62864 100644
--- a/test/functional/autocmd/autocmd_spec.lua
+++ b/test/functional/autocmd/autocmd_spec.lua
@@ -148,10 +148,10 @@ describe('autocmd', function()
funcs.execute('autocmd Tabnew'))
end)
- it('window works', function()
- -- Nvim uses a special window to execute certain actions for an invisible buffer,
- -- internally called autcmd_win and mentioned in the docs at :help E813
- -- Do some safety checks for redrawing and api accesses to this window.
+ it('internal `aucmd_win` window', function()
+ -- Nvim uses a special internal window `aucmd_win` to execute certain
+ -- actions for an invisible buffer (:help E813).
+ -- Check redrawing and API accesses to this window.
local screen = Screen.new(50, 10)
screen:attach()