From: José Fonseca <jose.r.fonseca@gmail.com> Date: Fri, 13 Apr 2012 13:57:08 +0000 (+0100) Subject: Prevent derreference after free when retracing glFeedbackBuffer/glSelectBuffer. X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=62abddc41c4f09d3688d7f56e097820cba8d16d3;p=apitrace Prevent derreference after free when retracing glFeedbackBuffer/glSelectBuffer. --- diff --git a/glretrace.py b/glretrace.py index 97a6ecc..cd7fe80 100644 --- a/glretrace.py +++ b/glretrace.py @@ -414,6 +414,12 @@ class GlRetracer(Retracer): print ' samples = max_samples;' print ' }' + # These parameters are referred beyond the call life-time + # TODO: Replace ad-hoc solution for bindable parameters with general one + if function.name in ('glFeedbackBuffer', 'glSelectBuffer') and arg.output: + print ' _allocator.bind(%s);' % arg.name + + if __name__ == '__main__': print r''' diff --git a/retrace.hpp b/retrace.hpp index dc11bb3..8ce15ad 100644 --- a/retrace.hpp +++ b/retrace.hpp @@ -26,7 +26,9 @@ #ifndef _RETRACE_HPP_ #define _RETRACE_HPP_ +#include <assert.h> #include <string.h> +#include <stdint.h> #include <list> #include <map> @@ -86,11 +88,11 @@ public: class ScopedAllocator { private: - void *next; + uintptr_t next; public: ScopedAllocator() : - next(NULL) { + next(0) { } inline void * @@ -99,15 +101,16 @@ public: return NULL; } - void * * buf = static_cast<void **>(malloc(sizeof(void *) + size)); + uintptr_t * buf = static_cast<uintptr_t *>(malloc(sizeof(uintptr_t) + size)); if (!buf) { return NULL; } *buf = next; - next = buf; + next = reinterpret_cast<uintptr_t>(buf); + assert((next & 1) == 0); - return &buf[1]; + return static_cast<void *>(&buf[1]); } template< class T > @@ -116,11 +119,29 @@ public: return static_cast<T *>(alloc(sizeof(T) * n)); } + /** + * Prevent this pointer from being automatically freed. + */ + template< class T > + inline void + bind(T *ptr) { + if (ptr) { + reinterpret_cast<uintptr_t *>(ptr)[-1] |= 1; + } + } + inline ~ScopedAllocator() { while (next) { - void *temp = *static_cast<void **>(next); - free(next); + uintptr_t temp = *reinterpret_cast<uintptr_t *>(next); + + bool bind = temp & 1; + temp &= ~1; + + if (!bind) { + free(reinterpret_cast<void *>(next)); + } + next = temp; } }