@@ -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 */
@@ -1967,6 +1971,23 @@ public synchronized boolean sessionResumed() throws SSLException {
19671971 return false ;
19681972 }
19691973
1974+ /**
1975+ * Helper method to track entry into an I/O operation.
1976+ * Increments the active operation counter to prevent premature freeSSL().
1977+ */
1978+ private boolean enterIOOperation () {
1979+ activeOperations .incrementAndGet ();
1980+ return true ;
1981+ }
1982+
1983+ /**
1984+ * Helper method to safely exit an I/O operation.
1985+ * Must be called for every successful enterIOOperation().
1986+ */
1987+ private void exitIOOperation () {
1988+ activeOperations .decrementAndGet ();
1989+ }
1990+
19701991 /**
19711992 * Internal private method to check if WolfSSLInputStream
19721993 * and WolfSSLOutputStream are closed.
@@ -2157,11 +2178,11 @@ public synchronized void close() throws IOException {
21572178 /* Connection is closed, free native WOLFSSL session
21582179 * to release native memory earlier than garbage
21592180 * collector might with finalize(), Don't free if we
2160- * have threads still waiting in poll/select or if
2181+ * have threads still waiting in poll/select, if
21612182 * our WolfSSLInputStream or WolfSSLOutputStream are
2162- * still open. */
2163- if (this .ssl .getThreadsBlockedInPoll () == 0 &&
2164- ioStreamsAreClosed ()) {
2183+ * still open, or if there are active I/O operations . */
2184+ if (( this .ssl .getThreadsBlockedInPoll () == 0 ) &&
2185+ ioStreamsAreClosed () && ( activeOperations . get () == 0 ) ) {
21652186 WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
21662187 () -> "calling this.ssl.freeSSL()" );
21672188 this .ssl .freeSSL ();
@@ -2171,7 +2192,8 @@ public synchronized void close() throws IOException {
21712192 () -> "deferring freeing this.ssl, threads " +
21722193 "blocked in poll: " +
21732194 this .ssl .getThreadsBlockedInPoll () +
2174- ", or streams not closed" );
2195+ ", streams not closed, or active operations: " +
2196+ activeOperations .get ());
21752197 }
21762198
21772199 /* Reset internal WolfSSLEngineHelper to null */
@@ -2710,6 +2732,11 @@ public synchronized int read(byte[] b, int off, int len)
27102732 "Array index out of bounds" );
27112733 }
27122734
2735+ /* Enter I/O operation to prevent use-after-free */
2736+ if (!socket .enterIOOperation ()) {
2737+ throw new SocketException ("Socket is closing" );
2738+ }
2739+
27132740 try {
27142741 int err ;
27152742 int timeout = socket .getSoTimeout ();
@@ -2775,6 +2802,9 @@ public synchronized int read(byte[] b, int off, int len)
27752802 * IllegalStateException to be thrown from
27762803 * WolfSSLSession.read(). Return as a SocketException here. */
27772804 throw new SocketException (e .getMessage ());
2805+ } finally {
2806+ /* Exit I/O operation */
2807+ socket .exitIOOperation ();
27782808 }
27792809
27802810 /* return number of bytes read */
@@ -2921,6 +2951,11 @@ public synchronized void write(byte[] b, int off, int len)
29212951 "Array index out of bounds" );
29222952 }
29232953
2954+ /* Enter I/O operation to prevent use-after-free */
2955+ if (!socket .enterIOOperation ()) {
2956+ throw new SocketException ("Socket is closing" );
2957+ }
2958+
29242959 try {
29252960 int err ;
29262961 int timeout = socket .getSoTimeout ();
@@ -2962,6 +2997,9 @@ public synchronized void write(byte[] b, int off, int len)
29622997 () -> "got IllegalStateException: " + e +
29632998 ", throwing IOException" );
29642999 throw new IOException (e );
3000+ } finally {
3001+ /* Exit I/O operation */
3002+ socket .exitIOOperation ();
29653003 }
29663004 }
29673005 } /* end WolfSSLOutputStream inner class */
0 commit comments