asan: Fix setting context non-current too much
bug: 74981595
+ avoid double frees in eglDestroy(Context|Surface)
Change-Id: Ie4801a8a2c0bc42fc26fcba2de81f3f830c59ae9
(cherry picked from commit 0c41152cda253edb3c9cef9e4b05dc18302aac2e)
diff --git a/system/egl/egl.cpp b/system/egl/egl.cpp
index 569338f..d291a94 100644
--- a/system/egl/egl.cpp
+++ b/system/egl/egl.cpp
@@ -160,12 +160,14 @@
}
#define VALIDATE_CONTEXT_RETURN(context,ret) \
- if (!(context)) { \
+ if (!(context) || !s_display.isContext((context))) { \
RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
}
#define VALIDATE_SURFACE_RETURN(surface, ret) \
if ((surface) != EGL_NO_SURFACE) { \
+ if (!s_display.isSurface((surface))) \
+ setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE); \
egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
if (s->dpy != (EGLDisplay)&s_display) \
setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
@@ -609,6 +611,11 @@
// Destroy a pending surface and set it to NULL.
static void s_destroyPendingSurfaceAndSetNull(EGLSurface* surface) {
+ if (!s_display.isSurface(surface)) {
+ *surface = NULL;
+ return;
+ }
+
egl_surface_t* surf = static_cast<egl_surface_t *>(*surface);
if (surf && surf->deletePending) {
delete surf;
@@ -1226,7 +1233,7 @@
tInfo->eglError = EGL_SUCCESS;
EGLContext_t* context = tInfo->currentContext;
- if (!context) return EGL_TRUE;
+ if (!context || !s_display.isContext(context)) return EGL_TRUE;
// The following code is doing pretty much the same thing as
// eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
@@ -1556,8 +1563,6 @@
EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
- if (!context) return EGL_TRUE;
-
if (context->flags & EGLContext_t::IS_CURRENT) {
context->deletePending = 1;
return EGL_TRUE;
@@ -1602,7 +1607,7 @@
if (tInfo->currentContext == context &&
(context == NULL ||
- (context && context->draw == draw && context->read == read))) {
+ (context && (context->draw == draw) && (context->read == read)))) {
return EGL_TRUE;
}
@@ -1732,8 +1737,9 @@
}
- if (tInfo->currentContext)
+ if (tInfo->currentContext && (tInfo->currentContext != context)) {
tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
+ }
//Now make current
tInfo->currentContext = context;
diff --git a/system/egl/eglDisplay.cpp b/system/egl/eglDisplay.cpp
index e2fb279..f593598 100644
--- a/system/egl/eglDisplay.cpp
+++ b/system/egl/eglDisplay.cpp
@@ -577,3 +577,16 @@
pthread_mutex_unlock(&m_surfaceLock);
}
+bool eglDisplay::isContext(EGLContext ctx) {
+ pthread_mutex_lock(&m_ctxLock);
+ bool res = m_contexts.find(ctx) != m_contexts.end();
+ pthread_mutex_unlock(&m_ctxLock);
+ return res;
+}
+
+bool eglDisplay::isSurface(EGLSurface surface) {
+ pthread_mutex_lock(&m_surfaceLock);
+ bool res = m_surfaces.find(surface) != m_surfaces.end();
+ pthread_mutex_unlock(&m_surfaceLock);
+ return res;
+}
diff --git a/system/egl/eglDisplay.h b/system/egl/eglDisplay.h
index ba39201..9fb6f07 100644
--- a/system/egl/eglDisplay.h
+++ b/system/egl/eglDisplay.h
@@ -67,6 +67,9 @@
void onDestroyContext(EGLContext ctx);
void onDestroySurface(EGLSurface surface);
+
+ bool isContext(EGLContext ctx);
+ bool isSurface(EGLSurface ctx);
private:
EGLClient_glesInterface *loadGLESClientAPI(const char *libName,
EGLClient_eglInterface *eglIface,