From 98dca8cd3cffd3f9dc1c920bbe8e6349877447b7 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Sun, 2 Jul 2023 03:58:20 +0200
Subject: GlueGen JavaCallback: Document native callback use-after-free
 potential (caught), zero-mem @ release

---
 src/java/com/jogamp/gluegen/CMethodBindingEmitter.java | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

(limited to 'src/java/com')

diff --git a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
index b2b9cbd..128f9ce 100644
--- a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
+++ b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
@@ -375,7 +375,10 @@ public class CMethodBindingEmitter extends FunctionEmitter {
                 returnStatement = "return;";
             }
             unit.emitln("  if( NULL == cb ) { fprintf(stderr, \"Info: Callback '"+staticCallbackName+"(..)': NULL "+userParamArgName+", skipping!\\n\"); "+returnStatement+" }");
-            unit.emitln("  T_"+jcbNativeBasename+" cb2 = *cb; // use a copy to avoid data-race between GetObjectRefType() and MonitorEnter()");
+            unit.emitln();
+            unit.emitln("  // Use-after-free of '*cb' possible up until after GetObjectRefType() check for a brief moment!");
+            unit.emitln("  // Use a copy to avoid data-race between GetObjectRefType() and MonitorEnter()\");");
+            unit.emitln("  T_"+jcbNativeBasename+" cb2 = *cb;");
             unit.emitln();
             unit.emitln("  jobjectRefType refType = (*env)->GetObjectRefType(env, cb2.lockObj);");
             unit.emitln("  if( 0 == refType ) { fprintf(stderr, \"Info: Callback '"+staticCallbackName+"(..)': User after free(lock), skipping!\\n\"); "+returnStatement+" }");
@@ -609,6 +612,8 @@ public class CMethodBindingEmitter extends FunctionEmitter {
         unit.emitln("    (*env)->DeleteGlobalRef(env, nativeUserParam->lockObj);");
         unit.emitln("    (*env)->DeleteGlobalRef(env, nativeUserParam->cbFunc);");
         unit.emitln("    (*env)->DeleteGlobalRef(env, nativeUserParam->userParam);");
+        unit.emitln("    // Ensure even w/ use-after-free jobject refs are NULL and invalid to avoid accidental reuse.");
+        unit.emitln("    memset(nativeUserParam, 0, sizeof(T_"+jcbNativeBasename+"));");
         unit.emitln("    free(nativeUserParam);");
         unit.emitln("  }");
         unit.emitln("}");
-- 
cgit v1.2.3