@@ -80,6 +80,10 @@ public class WolfSSLSocket extends SSLSocket {
8080 private WolfSSLInputStream inStream ;
8181 private WolfSSLOutputStream outStream ;
8282
83+ /* Track active I/O operations to prevent use-after-free */
84+ private final java .util .concurrent .atomic .AtomicInteger activeOperations =
85+ new java .util .concurrent .atomic .AtomicInteger (0 );
86+
8387 private ArrayList <HandshakeCompletedListener > hsListeners = null ;
8488
8589 /** TLS handshake initialization called */
@@ -1972,6 +1976,22 @@ public synchronized boolean sessionResumed() throws SSLException {
19721976 return false ;
19731977 }
19741978
1979+ /**
1980+ * Helper method to track entry into an I/O operation.
1981+ * Increments the active operation counter to prevent premature freeSSL().
1982+ */
1983+ private void enterIOOperation () {
1984+ activeOperations .incrementAndGet ();
1985+ }
1986+
1987+ /**
1988+ * Helper method to safely exit an I/O operation.
1989+ * Must be called for every successful enterIOOperation().
1990+ */
1991+ private void exitIOOperation () {
1992+ activeOperations .decrementAndGet ();
1993+ }
1994+
19751995 /**
19761996 * Internal private method to check if WolfSSLInputStream
19771997 * and WolfSSLOutputStream are closed.
@@ -2168,12 +2188,12 @@ public synchronized void close() throws IOException {
21682188 /* Connection is closed, free native WOLFSSL session
21692189 * to release native memory earlier than garbage
21702190 * collector might with finalize(), Don't free if we
2171- * have threads still waiting in poll/select or if
2191+ * have threads still waiting in poll/select, if
21722192 * our WolfSSLInputStream or WolfSSLOutputStream are
2173- * still open. */
2193+ * still open, or if there are active I/O operations . */
21742194 if (this .ssl != null ) {
2175- if (this .ssl .getThreadsBlockedInPoll () == 0 &&
2176- ioStreamsAreClosed ()) {
2195+ if (( this .ssl .getThreadsBlockedInPoll () == 0 ) &&
2196+ ioStreamsAreClosed () && ( activeOperations . get () == 0 ) ) {
21772197 WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
21782198 () -> "calling this.ssl.freeSSL()" );
21792199 this .ssl .freeSSL ();
@@ -2183,7 +2203,8 @@ public synchronized void close() throws IOException {
21832203 () -> "deferring freeing this.ssl, threads " +
21842204 "blocked in poll: " +
21852205 this .ssl .getThreadsBlockedInPoll () +
2186- ", or streams not closed" );
2206+ ", streams not closed, or active operations: " +
2207+ activeOperations .get ());
21872208 }
21882209 }
21892210
@@ -2725,6 +2746,9 @@ public synchronized int read(byte[] b, int off, int len)
27252746 "Array index out of bounds" );
27262747 }
27272748
2749+ /* Enter I/O operation to prevent use-after-free */
2750+ socket .enterIOOperation ();
2751+
27282752 try {
27292753 int err ;
27302754 int timeout = socket .getSoTimeout ();
@@ -2790,6 +2814,9 @@ public synchronized int read(byte[] b, int off, int len)
27902814 * IllegalStateException to be thrown from
27912815 * WolfSSLSession.read(). Return as a SocketException here. */
27922816 throw new SocketException (e .getMessage ());
2817+ } finally {
2818+ /* Exit I/O operation */
2819+ socket .exitIOOperation ();
27932820 }
27942821
27952822 /* return number of bytes read */
@@ -2936,6 +2963,9 @@ public synchronized void write(byte[] b, int off, int len)
29362963 "Array index out of bounds" );
29372964 }
29382965
2966+ /* Enter I/O operation to prevent use-after-free */
2967+ socket .enterIOOperation ();
2968+
29392969 try {
29402970 int err ;
29412971 int timeout = socket .getSoTimeout ();
@@ -2977,6 +3007,9 @@ public synchronized void write(byte[] b, int off, int len)
29773007 () -> "got IllegalStateException: " + e +
29783008 ", throwing IOException" );
29793009 throw new IOException (e );
3010+ } finally {
3011+ /* Exit I/O operation */
3012+ socket .exitIOOperation ();
29803013 }
29813014 }
29823015 } /* end WolfSSLOutputStream inner class */
0 commit comments