From 1cfcd8327707d27693a0fcdcfc6a238acc47a4e2 Mon Sep 17 00:00:00 2001
From: Timothy Arceri <tarceri@itsqueeze.com>
Date: Mon, 6 Jul 2026 14:27:55 +1000
Subject: [PATCH] guicast: dont free gl fb config until destruction

BC_DisplayInfo::gl_fb_config() uses if-statements to check if
fb_cfgs and vis_info are null but when BC_DisplayInfo::gl_probe()
frees them it doesn't clear the pointers. This can lead to use
after free and double free issues. Instead free gl fb cfgs
on destruction.

Fixes: 59e74f262d7b
---
 cinelerra-5.1/guicast/bcdisplayinfo.C | 32 +++++++++++++++------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/cinelerra-5.1/guicast/bcdisplayinfo.C b/cinelerra-5.1/guicast/bcdisplayinfo.C
index 62d58338..5e153dd9 100644
--- a/cinelerra-5.1/guicast/bcdisplayinfo.C
+++ b/cinelerra-5.1/guicast/bcdisplayinfo.C
@@ -63,6 +63,10 @@ BC_DisplayInfo::BC_DisplayInfo(const char *display_name, int show_error)
 BC_DisplayInfo::~BC_DisplayInfo()
 {
 	if( xinerama_info ) XFree(xinerama_info);
+#ifdef HAVE_GL
+	if( fb_cfgs ) XFree(fb_cfgs);
+	if( vis_info ) XFree(vis_info);
+#endif
 #ifndef SINGLE_THREAD
 	XCloseDisplay(display);
 #endif
@@ -212,19 +216,21 @@ int BC_DisplayInfo::gl_fb_config()
 		fb_cfgs = glXChooseFBConfig(display, scrnum, fb_attrs+2, &ncfgs);
 		if( fb_cfgs && ncfgs ) break;
 		fb_cfgs = glXChooseFBConfig(display, scrnum, fb_attrs+0, &ncfgs);
+
+		if( fb_cfgs && ncfgs ) {
+			for( int i=0; !vis_info && i<ncfgs; ++i )
+				vis_info = glXGetVisualFromFBConfig(display, cfg=fb_cfgs[i]);
+		}
+		if( vis_info ) {
+			vis = vis_info->visual;
+			depth = vis_info->depth;
+		}
+		else {
+			printf("%s\n", "BC_DisplayInfo::gl_fb_config failed");
+			cfg = 0;
+		}
 	} while(0);
-	if( fb_cfgs && ncfgs ) {
-		for( int i=0; !vis_info && i<ncfgs; ++i )
-			vis_info = glXGetVisualFromFBConfig(display, cfg=fb_cfgs[i]);
-	}
-	if( vis_info ) {
-		vis = vis_info->visual;
-		depth = vis_info->depth;
-	}
-	else {
-		printf("%s\n", "BC_DisplayInfo::gl_fb_config failed");
-		cfg = 0;
-	}
+
 	return 0;
 }
 
@@ -246,8 +252,6 @@ int BC_DisplayInfo::gl_probe(Window win)
 	glXMakeContextCurrent(display, None, None, 0);
 	if( glx_ctx ) glXDestroyContext(display, glx_ctx);
 	if( glx_win ) glXDestroyWindow(display, glx_win);
-	if( fb_cfgs ) XFree(fb_cfgs);
-	if( vis_info ) XFree(vis_info);
 	return 0;
 }
 #endif
-- 
2.54.0

