Index: libroar/buffer.c
===================================================================
--- libroar/buffer.c	(revision 4989)
+++ libroar/buffer.c	(revision 5011)
@@ -57,5 +57,30 @@
 };
 
-#define _ckbuf(m)  if ( buf == NULL || (m) ) { roar_err_set(ROAR_ERROR_FAULT); return -1; }
+#define _ckbuf_free(m)  if ( buf == NULL || (m) ) { roar_err_set(ROAR_ERROR_FAULT); return -1; }
+#define _ckbuf(m)  _ckbuf_free((m)); if ( _ckmem_corruption(buf) == -1 ) return -1;
+
+static int inline _ckmem_corruption(struct roar_buffer * buf) {
+ int flags = buf->flags & (ROAR_BUFFER_FLAG_USEABLE|ROAR_BUFFER_FLAG_FREED);
+
+ ROAR_DBG("_ckmem_corruption(buf=%p{.flags=0x%.4x, ...} = ?", buf, buf->flags);
+
+ if ( flags == ROAR_BUFFER_FLAG_USEABLE ) {
+  // seems ok, continue with next check.
+ } else if ( flags == ROAR_BUFFER_FLAG_FREED ) {
+  roar_panic(ROAR_FATAL_ERROR_MEMORY_USED_AFTER_FREE, NULL);
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ } else {
+  roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
+  roar_err_set(ROAR_ERROR_BADCKSUM);
+  return -1;
+ }
+
+ if ( buf->refc == 0 ) {
+  roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
+ }
+
+ return 0;
+}
 
 int roar_buffer_new_data (struct roar_buffer ** buf, size_t len, void ** data) {
@@ -93,5 +118,5 @@
  ROAR_DBG("buffer_new(buf=%p, len=%i) = ?", buf, len);
 
- _ckbuf(data == NULL)
+ _ckbuf_free(data == NULL)
 
  if ((new = roar_mm_malloc(sizeof(struct roar_buffer))) == NULL) {
@@ -104,5 +129,5 @@
  new->data      = data;
 
- new->flags     = ROAR_BUFFER_FLAG_NONE|ROAR_BUFFER_FLAG_NOFREE;
+ new->flags     = ROAR_BUFFER_FLAG_NONE|ROAR_BUFFER_FLAG_NOFREE|ROAR_BUFFER_FLAG_USEABLE;
  new->type      = -1;
 
@@ -129,7 +154,21 @@
 
 int roar_buffer_unref     (struct roar_buffer * buf) {
- struct roar_buffer * next;
-
- _ckbuf(0)
+ struct roar_buffer * next, * cur;
+ int flags;
+
+ ROAR_DBG("roar_buffer_unref(buf=%p) = ?", buf);
+
+ _ckbuf_free(0)
+
+ ROAR_DBG("roar_buffer_unref(buf=%p) = ?", buf);
+
+ flags = buf->flags & (ROAR_BUFFER_FLAG_USEABLE|ROAR_BUFFER_FLAG_FREED);
+ if ( flags == ROAR_BUFFER_FLAG_FREED ) {
+  roar_panic(ROAR_FATAL_ERROR_MEMORY_DOUBLE_FREE, NULL);
+ }
+
+ _ckmem_corruption(buf);
+
+ ROAR_DBG("roar_buffer_unref(buf=%p) = ?", buf);
 
  if ( buf->refc == 0 ) {
@@ -141,20 +180,42 @@
  buf->refc--;
 
- if ( buf->refc )
+ if ( buf->refc ) {
+  ROAR_DBG("roar_buffer_unref(buf=%p) = 0", buf);
   return 0;
-
- while ((next = buf->next)) {
-  if ( roar_buffer_get_flag(buf, ROAR_BUFFER_FLAG_NOFREE) != 1 )
-   roar_mm_free(buf->data);
-
-  roar_mm_free(buf);
-  buf = next;
- }
-
- if ( roar_buffer_get_flag(buf, ROAR_BUFFER_FLAG_NOFREE) != 1 )
+ }
+
+ ROAR_DBG("roar_buffer_unref(buf=%p) = ?", buf);
+
+ cur = buf->next;
+ while (cur != NULL) {
+  flags = cur->flags & (ROAR_BUFFER_FLAG_USEABLE|ROAR_BUFFER_FLAG_FREED);
+  if ( flags == ROAR_BUFFER_FLAG_FREED ) {
+   roar_panic(ROAR_FATAL_ERROR_MEMORY_DOUBLE_FREE, NULL);
+  }
+
+  ROAR_DBG("roar_buffer_unref(buf=%p) = ?", buf);
+
+  _ckmem_corruption(cur);
+
+  if ( roar_buffer_get_flag(cur, ROAR_BUFFER_FLAG_NOFREE) != 1 )
+   roar_mm_free(cur->data);
+
+  cur->flags = ROAR_BUFFER_FLAG_FREED;
+  next = cur->next;
+  roar_mm_free(cur);
+  cur = next;
+ }
+
+ ROAR_DBG("roar_buffer_unref(buf=%p) = ?", buf);
+
+ if ( !(buf->flags & ROAR_BUFFER_FLAG_NOFREE) )
   roar_mm_free(buf->data);
 
+ ROAR_DBG("roar_buffer_unref(buf=%p): setting flags = ROAR_BUFFER_FLAG_FREED", buf);
+ buf->flags = ROAR_BUFFER_FLAG_FREED;
+
  roar_mm_free(buf);
 
+ ROAR_DBG("roar_buffer_unref(buf=%p) = 0", buf);
  return 0;
 }
@@ -238,5 +299,5 @@
  struct roar_buffer * n;
 
- _ckbuf(0)
+ _ckbuf_free(0)
 
  if ( len == 0 ) {
@@ -293,5 +354,5 @@
  void * cd;
 
- _ckbuf(len == NULL || data == NULL);
+ _ckbuf_free(len == NULL || data == NULL);
 
  if ( *buf == NULL ) {
@@ -305,4 +366,6 @@
 
  *len = 0;
+
+ _ckmem_corruption(cur);
 
  while (todo && cur != NULL) {
@@ -336,4 +399,5 @@
    if ( roar_buffer_next(&cur) == -1 )
     return -1;
+   _ckmem_corruption(cur);
   }
 
