Keep track of size of allocations as well and report this information when reporting leaks; also add realloc support and some belt-and-suspenders stuff to stack formatting code.
diff --git a/OpenSSL/test/util.py b/OpenSSL/test/util.py
index 88dc79b..e57d55a 100644
--- a/OpenSSL/test/util.py
+++ b/OpenSSL/test/util.py
@@ -52,7 +52,7 @@
             stacks = memdbg.heap[p]
             # Eventually look at multiple stacks for the realloc() case.  For
             # now just look at the original allocation location.
-            (python_stack, c_stack) = stacks[0]
+            (size, python_stack, c_stack) = stacks[0]
 
             stack = traceback.format_list(python_stack)[:-1]
 
@@ -89,34 +89,43 @@
             # Notice the stack is upside down compared to a Python traceback.
             # Identify the start and end of interesting bits and stuff it into the stack we report.
 
+            saved = list(c_stack)
+
             # Figure the first interesting frame will be after a the cffi-compiled module
-            while '/__pycache__/_cffi__' not in c_stack[-1]:
+            while c_stack and '/__pycache__/_cffi__' not in c_stack[-1]:
                 c_stack.pop()
 
             # Figure the last interesting frame will always be CRYPTO_malloc,
             # since that's where we hooked in to things.
-            while 'CRYPTO_malloc' not in c_stack[0]:
+            while c_stack and 'CRYPTO_malloc' not in c_stack[0] and 'CRYPTO_realloc' not in c_stack[0]:
                 c_stack.pop(0)
 
-            c_stack.reverse()
+            if c_stack:
+                c_stack.reverse()
+            else:
+                c_stack = saved[::-1]
             stack.extend([frame + "\n" for frame in c_stack])
 
             # XXX :(
             ptr = int(str(p).split()[-1][:-1], 16)
-            stack.insert(0, "Leaked 0x%x at:\n" % (ptr,))
+            stack.insert(0, "Leaked %d bytes (0x%x) at:\n" % (size, ptr))
             return "".join(stack)
 
         # Clean up some long-lived allocations so they won't be reported as
         # memory leaks.
         api.CRYPTO_cleanup_all_ex_data()
+        api.ERR_remove_thread_state(api.NULL)
 
         after = set(memdbg.heap)
         leak = after - self._before
         if leak:
-            reasons = []
+            total = 0
+            reasons = [""]
             for p in leak:
+                total += memdbg.heap[p][-1][0]
                 reasons.append(format_leak(p))
-                del memdbg.heap[p]
+                memdbg.free(p)
+            reasons.append("\nLeaked %d bytes in %d pointers\n" % (total, len(leak)))
             self.fail('\n'.join(reasons))
 
         if False and self._temporaryFiles is not None: