@@ -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.
@@ -2159,12 +2179,12 @@ public synchronized void close() throws IOException {
21592179 /* Connection is closed, free native WOLFSSL session
21602180 * to release native memory earlier than garbage
21612181 * collector might with finalize(), Don't free if we
2162- * have threads still waiting in poll/select or if
2182+ * have threads still waiting in poll/select, if
21632183 * our WolfSSLInputStream or WolfSSLOutputStream are
2164- * still open. */
2184+ * still open, or if there are active I/O operations . */
21652185 if (this .ssl != null ) {
2166- if (this .ssl .getThreadsBlockedInPoll () == 0 &&
2167- ioStreamsAreClosed ()) {
2186+ if (( this .ssl .getThreadsBlockedInPoll () == 0 ) &&
2187+ ioStreamsAreClosed () && ( activeOperations . get () == 0 ) ) {
21682188 WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
21692189 () -> "calling this.ssl.freeSSL()" );
21702190 this .ssl .freeSSL ();
@@ -2174,7 +2194,8 @@ public synchronized void close() throws IOException {
21742194 () -> "deferring freeing this.ssl, threads " +
21752195 "blocked in poll: " +
21762196 this .ssl .getThreadsBlockedInPoll () +
2177- ", or streams not closed" );
2197+ ", streams not closed, or active operations: " +
2198+ activeOperations .get ());
21782199 }
21792200 }
21802201
@@ -2714,6 +2735,9 @@ public synchronized int read(byte[] b, int off, int len)
27142735 "Array index out of bounds" );
27152736 }
27162737
2738+ /* Enter I/O operation to prevent use-after-free */
2739+ socket .enterIOOperation ();
2740+
27172741 try {
27182742 int err ;
27192743 int timeout = socket .getSoTimeout ();
@@ -2779,6 +2803,9 @@ public synchronized int read(byte[] b, int off, int len)
27792803 * IllegalStateException to be thrown from
27802804 * WolfSSLSession.read(). Return as a SocketException here. */
27812805 throw new SocketException (e .getMessage ());
2806+ } finally {
2807+ /* Exit I/O operation */
2808+ socket .exitIOOperation ();
27822809 }
27832810
27842811 /* return number of bytes read */
@@ -2925,6 +2952,9 @@ public synchronized void write(byte[] b, int off, int len)
29252952 "Array index out of bounds" );
29262953 }
29272954
2955+ /* Enter I/O operation to prevent use-after-free */
2956+ socket .enterIOOperation ();
2957+
29282958 try {
29292959 int err ;
29302960 int timeout = socket .getSoTimeout ();
@@ -2966,6 +2996,9 @@ public synchronized void write(byte[] b, int off, int len)
29662996 () -> "got IllegalStateException: " + e +
29672997 ", throwing IOException" );
29682998 throw new IOException (e );
2999+ } finally {
3000+ /* Exit I/O operation */
3001+ socket .exitIOOperation ();
29693002 }
29703003 }
29713004 } /* end WolfSSLOutputStream inner class */
0 commit comments