@@ -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,22 @@ 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 void enterIOOperation () {
1979+ activeOperations .incrementAndGet ();
1980+ }
1981+
1982+ /**
1983+ * Helper method to safely exit an I/O operation.
1984+ * Must be called for every successful enterIOOperation().
1985+ */
1986+ private void exitIOOperation () {
1987+ activeOperations .decrementAndGet ();
1988+ }
1989+
19701990 /**
19711991 * Internal private method to check if WolfSSLInputStream
19721992 * and WolfSSLOutputStream are closed.
@@ -2157,11 +2177,11 @@ public synchronized void close() throws IOException {
21572177 /* Connection is closed, free native WOLFSSL session
21582178 * to release native memory earlier than garbage
21592179 * collector might with finalize(), Don't free if we
2160- * have threads still waiting in poll/select or if
2180+ * have threads still waiting in poll/select, if
21612181 * our WolfSSLInputStream or WolfSSLOutputStream are
2162- * still open. */
2163- if (this .ssl .getThreadsBlockedInPoll () == 0 &&
2164- ioStreamsAreClosed ()) {
2182+ * still open, or if there are active I/O operations . */
2183+ if (( this .ssl .getThreadsBlockedInPoll () == 0 ) &&
2184+ ioStreamsAreClosed () && ( activeOperations . get () == 0 ) ) {
21652185 WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
21662186 () -> "calling this.ssl.freeSSL()" );
21672187 this .ssl .freeSSL ();
@@ -2171,7 +2191,8 @@ public synchronized void close() throws IOException {
21712191 () -> "deferring freeing this.ssl, threads " +
21722192 "blocked in poll: " +
21732193 this .ssl .getThreadsBlockedInPoll () +
2174- ", or streams not closed" );
2194+ ", streams not closed, or active operations: " +
2195+ activeOperations .get ());
21752196 }
21762197
21772198 /* Reset internal WolfSSLEngineHelper to null */
@@ -2710,6 +2731,9 @@ public synchronized int read(byte[] b, int off, int len)
27102731 "Array index out of bounds" );
27112732 }
27122733
2734+ /* Enter I/O operation to prevent use-after-free */
2735+ socket .enterIOOperation ();
2736+
27132737 try {
27142738 int err ;
27152739 int timeout = socket .getSoTimeout ();
@@ -2775,6 +2799,9 @@ public synchronized int read(byte[] b, int off, int len)
27752799 * IllegalStateException to be thrown from
27762800 * WolfSSLSession.read(). Return as a SocketException here. */
27772801 throw new SocketException (e .getMessage ());
2802+ } finally {
2803+ /* Exit I/O operation */
2804+ socket .exitIOOperation ();
27782805 }
27792806
27802807 /* return number of bytes read */
@@ -2921,6 +2948,9 @@ public synchronized void write(byte[] b, int off, int len)
29212948 "Array index out of bounds" );
29222949 }
29232950
2951+ /* Enter I/O operation to prevent use-after-free */
2952+ socket .enterIOOperation ();
2953+
29242954 try {
29252955 int err ;
29262956 int timeout = socket .getSoTimeout ();
@@ -2962,6 +2992,9 @@ public synchronized void write(byte[] b, int off, int len)
29622992 () -> "got IllegalStateException: " + e +
29632993 ", throwing IOException" );
29642994 throw new IOException (e );
2995+ } finally {
2996+ /* Exit I/O operation */
2997+ socket .exitIOOperation ();
29652998 }
29662999 }
29673000 } /* end WolfSSLOutputStream inner class */
0 commit comments