This is an automated email from the ASF dual-hosted git repository.

ffang pushed a commit to branch 4.0.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/4.0.x-fixes by this push:
     new 715c27e3d9e Fix OpenScanHub findings: race conditions and resource 
leaks (#2781)
715c27e3d9e is described below

commit 715c27e3d9e567b5cf057fe09aef92d53f775f8b
Author: Roman Stepaniuk <[email protected]>
AuthorDate: Tue Jan 13 13:35:24 2026 +0100

    Fix OpenScanHub findings: race conditions and resource leaks (#2781)
    
    Co-authored-by: Roman Stepaniuk <[email protected]>
    (cherry picked from commit f512d07036d232fc9c63a9e3fd0eacd83a4a3d19)
    (cherry picked from commit 75751ee4a5f60aec3ccd7478eaf92c23d96142b2)
---
 .../cxf/attachment/AttachmentDeserializer.java     |  9 ++--
 .../cxf/bus/extension/ExtensionManagerBus.java     | 10 ++--
 .../org/apache/cxf/common/util/StreamPrinter.java  | 13 ++++--
 .../apache/cxf/configuration/jsse/SSLUtils.java    |  4 +-
 .../src/main/java/httpsdemo/client/Client.java     |  4 +-
 .../main/java/demo/jaxrs/search/client/Client.java |  6 ++-
 .../jaxws/client/DumpingClassLoaderCapturer.java   |  4 +-
 .../src/main/java/demo/hw/client/Get.java          | 53 ++++++++++++++++++----
 .../java/org/apache/cxf/aegis/AegisContext.java    |  8 ++--
 .../org/apache/cxf/javascript/cxf-utils.js         |  2 +-
 .../apache/cxf/jaxrs/client/spec/ClientImpl.java   | 10 ++--
 .../jwe/AbstractContentEncryptionAlgorithm.java    | 30 ++++++------
 .../security/oauth2/client/CodeAuthSupplier.java   | 18 ++++----
 .../apache/cxf/transport/servlet/CXFServlet.java   |  4 +-
 .../servicelist/ServiceListGeneratorServlet.java   |  6 ++-
 15 files changed, 115 insertions(+), 66 deletions(-)

diff --git 
a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java 
b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
index 9782c8be113..1a71ab463a2 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
@@ -249,10 +249,13 @@ public class AttachmentDeserializer {
                 if (!ads.isCached()) {
                     ads.cache(message);
                 }
-            } else if (s.getInputStream() instanceof DelegatingInputStream) {
-                cache((DelegatingInputStream) s.getInputStream());
             } else {
-                //assume a normal stream that is already cached
+                InputStream is = s.getInputStream();
+                if (is instanceof DelegatingInputStream) {
+                    cache((DelegatingInputStream) is);
+                } else {
+                    //assume a normal stream that is already cached
+                }
             }
         }
     }
diff --git 
a/core/src/main/java/org/apache/cxf/bus/extension/ExtensionManagerBus.java 
b/core/src/main/java/org/apache/cxf/bus/extension/ExtensionManagerBus.java
index 4c12756d6ac..fd8ddd6a449 100644
--- a/core/src/main/java/org/apache/cxf/bus/extension/ExtensionManagerBus.java
+++ b/core/src/main/java/org/apache/cxf/bus/extension/ExtensionManagerBus.java
@@ -281,16 +281,16 @@ public class ExtensionManagerBus extends 
AbstractBasicInterceptorProvider implem
     }
 
     public void shutdown(boolean wait) {
-        if (state == BusState.SHUTTING_DOWN) {
-            return;
+        synchronized (this) {
+            if (state == BusState.SHUTTING_DOWN) {
+                return;
+            }
+            state = BusState.SHUTTING_DOWN;
         }
         BusLifeCycleManager lifeCycleManager = 
this.getExtension(BusLifeCycleManager.class);
         if (null != lifeCycleManager) {
             lifeCycleManager.preShutdown();
         }
-        synchronized (this) {
-            state = BusState.SHUTTING_DOWN;
-        }
         destroyBeans();
         synchronized (this) {
             state = BusState.SHUTDOWN;
diff --git a/core/src/main/java/org/apache/cxf/common/util/StreamPrinter.java 
b/core/src/main/java/org/apache/cxf/common/util/StreamPrinter.java
index fa8828764d5..564c64cc487 100644
--- a/core/src/main/java/org/apache/cxf/common/util/StreamPrinter.java
+++ b/core/src/main/java/org/apache/cxf/common/util/StreamPrinter.java
@@ -39,13 +39,12 @@ class StreamPrinter extends Thread {
 
     @Override
     public void run() {
-        try {
+        try (InputStreamReader isr = new InputStreamReader(is);
+             BufferedReader br = new BufferedReader(isr)) {
             PrintWriter pw = null;
             if (os != null) {
                 pw = new PrintWriter(os);
             }
-            InputStreamReader isr = new InputStreamReader(is);
-            BufferedReader br = new BufferedReader(isr);
             String line = br.readLine();
             while (line != null) {
                 if (pw != null) {
@@ -58,6 +57,14 @@ class StreamPrinter extends Thread {
             }
         } catch (IOException ioe) {
             throw new RuntimeException(ioe);
+        } finally {
+            try {
+                if (is != null) {
+                    is.close();
+                }
+            } catch (IOException e) {
+                // Ignore close exception
+            }
         }
     }
 }
diff --git a/core/src/main/java/org/apache/cxf/configuration/jsse/SSLUtils.java 
b/core/src/main/java/org/apache/cxf/configuration/jsse/SSLUtils.java
index 9c0e4e318d9..57a44026167 100644
--- a/core/src/main/java/org/apache/cxf/configuration/jsse/SSLUtils.java
+++ b/core/src/main/java/org/apache/cxf/configuration/jsse/SSLUtils.java
@@ -22,9 +22,9 @@ package org.apache.cxf.configuration.jsse;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.security.KeyManagementException;
 import java.security.KeyStore;
 import java.security.NoSuchAlgorithmException;
@@ -196,7 +196,7 @@ public final class SSLUtils {
         if (fileName == null) {
             return null;
         }
-        Path path = FileSystems.getDefault().getPath(fileName);
+        Path path = Paths.get(fileName);
         return Files.readAllBytes(path);
     }
 
diff --git 
a/distribution/src/main/release/samples/jax_rs/basic_https/src/main/java/httpsdemo/client/Client.java
 
b/distribution/src/main/release/samples/jax_rs/basic_https/src/main/java/httpsdemo/client/Client.java
index d6d4e56645c..918d44b077b 100644
--- 
a/distribution/src/main/release/samples/jax_rs/basic_https/src/main/java/httpsdemo/client/Client.java
+++ 
b/distribution/src/main/release/samples/jax_rs/basic_https/src/main/java/httpsdemo/client/Client.java
@@ -51,7 +51,9 @@ public final class Client {
         String keyStoreLoc = "src/main/config/clientKeystore.jks";
 
         KeyStore keyStore = KeyStore.getInstance("JKS");
-        keyStore.load(new FileInputStream(keyStoreLoc), 
"cspass".toCharArray());
+        try (FileInputStream fis = new FileInputStream(keyStoreLoc)) {
+            keyStore.load(fis, "cspass".toCharArray());
+        }
 
         SSLContext sslcontext = SSLContexts.custom()
                 .loadTrustMaterial(keyStore, null)
diff --git 
a/distribution/src/main/release/samples/jax_rs/search/src/main/java/demo/jaxrs/search/client/Client.java
 
b/distribution/src/main/release/samples/jax_rs/search/src/main/java/demo/jaxrs/search/client/Client.java
index 091b0812ed5..36f47e80122 100644
--- 
a/distribution/src/main/release/samples/jax_rs/search/src/main/java/demo/jaxrs/search/client/Client.java
+++ 
b/distribution/src/main/release/samples/jax_rs/search/src/main/java/demo/jaxrs/search/client/Client.java
@@ -20,6 +20,7 @@
 package demo.jaxrs.search.client;
 
 import java.io.IOException;
+import java.io.InputStream;
 
 import org.apache.cxf.helpers.IOUtils;
 import org.apache.http.client.methods.CloseableHttpResponse;
@@ -99,7 +100,10 @@ public final class Client {
 
         final HttpPost post = new HttpPost(url);
         MultipartEntity entity = new MultipartEntity();
-        byte[] bytes = 
IOUtils.readBytesFromStream(Client.class.getResourceAsStream("/" + filename));
+        byte[] bytes;
+        try (InputStream is = Client.class.getResourceAsStream("/" + 
filename)) {
+            bytes = IOUtils.readBytesFromStream(is);
+        }
         entity.addPart(filename, new ByteArrayBody(bytes, filename));
 
         post.setEntity(entity);
diff --git 
a/distribution/src/main/release/samples/jaxws_graalvm_dynamic/client/src/main/java/demo/jaxws/client/DumpingClassLoaderCapturer.java
 
b/distribution/src/main/release/samples/jaxws_graalvm_dynamic/client/src/main/java/demo/jaxws/client/DumpingClassLoaderCapturer.java
index c713de90dbd..b7c819d25e6 100644
--- 
a/distribution/src/main/release/samples/jaxws_graalvm_dynamic/client/src/main/java/demo/jaxws/client/DumpingClassLoaderCapturer.java
+++ 
b/distribution/src/main/release/samples/jaxws_graalvm_dynamic/client/src/main/java/demo/jaxws/client/DumpingClassLoaderCapturer.java
@@ -35,8 +35,8 @@ public class DumpingClassLoaderCapturer implements 
GeneratedClassClassLoaderCapt
     private final Map<String, byte[]> classes = new ConcurrentHashMap<>();
     
     public void dumpTo(File file) throws IOException {
-        if (!file.exists()) 
-            Files.createDirectories(file.toPath());{
+        if (!file.exists()) {
+            Files.createDirectories(file.toPath());
         }
         
         if (!file.isDirectory()) {
diff --git 
a/distribution/src/main/release/samples/js_browser_client_simple/src/main/java/demo/hw/client/Get.java
 
b/distribution/src/main/release/samples/js_browser_client_simple/src/main/java/demo/hw/client/Get.java
index 4b79bc9d878..390fd05f52d 100644
--- 
a/distribution/src/main/release/samples/js_browser_client_simple/src/main/java/demo/hw/client/Get.java
+++ 
b/distribution/src/main/release/samples/js_browser_client_simple/src/main/java/demo/hw/client/Get.java
@@ -46,8 +46,14 @@ public final class Get {
         System.out.println("Invoking server through HTTP GET to invoke sayHi");
 
         InputStream in = httpConnection.getInputStream();
-        StreamSource source = new StreamSource(in);
-        printSource(source);
+        try {
+            StreamSource source = new StreamSource(in);
+            printSource(source);
+        } finally {
+            if (in != null) {
+                in.close();
+            }
+        }
 
         // Sent HTTP GET request to invoke greetMe FAULT
         target = "http://localhost:9000/SoapContext/SoapPort/greetMe/me/CXF";;
@@ -58,14 +64,26 @@ public final class Get {
 
         try {
             in = httpConnection.getInputStream();
-            source = new StreamSource(in);
-            printSource(source);
+            try {
+                StreamSource source = new StreamSource(in);
+                printSource(source);
+            } finally {
+                if (in != null) {
+                    in.close();
+                }
+            }
         } catch (Exception e) {
             System.err.println("GreetMe Fault: " + e.getMessage());
         }
         InputStream err = httpConnection.getErrorStream();
-        source = new StreamSource(err);
-        printSource(source);
+        if (err != null) {
+            try {
+                StreamSource source = new StreamSource(err);
+                printSource(source);
+            } finally {
+                err.close();
+            }
+        }
 
         // Sent HTTP GET request to invoke greetMe
         target = 
"http://localhost:9000/SoapContext/SoapPort/greetMe/requestType/CXF";;
@@ -75,8 +93,14 @@ public final class Get {
         System.out.println("Invoking server through HTTP GET to invoke 
greetMe");
 
         in = httpConnection.getInputStream();
-        source = new StreamSource(in);
-        printSource(source);
+        try {
+            StreamSource source = new StreamSource(in);
+            printSource(source);
+        } finally {
+            if (in != null) {
+                in.close();
+            }
+        }
 
         // Sent HTTP GET request to invoke pingMe
         target = "http://localhost:9000/SoapContext/SoapPort/pingMe";;
@@ -87,12 +111,21 @@ public final class Get {
 
         try {
             in = httpConnection.getInputStream();
+            if (in != null) {
+                in.close();
+            }
         } catch (Exception e) {
             System.out.println("PingMe fault raised");
         }
         err = httpConnection.getErrorStream();
-        source = new StreamSource(err);
-        printSource(source);
+        if (err != null) {
+            try {
+                StreamSource source = new StreamSource(err);
+                printSource(source);
+            } finally {
+                err.close();
+            }
+        }
     }
 
     private static void printSource(Source source) {
diff --git 
a/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/AegisContext.java 
b/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/AegisContext.java
index eddcbb9e4e2..5252c2d1e18 100644
--- a/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/AegisContext.java
+++ b/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/AegisContext.java
@@ -18,6 +18,8 @@
  */
 package org.apache.cxf.aegis;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.lang.reflect.Array;
 import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.ParameterizedType;
@@ -286,9 +288,9 @@ public class AegisContext {
     }
 
     private Document getSchemaDocument(String resourcePath) {
-        try {
-            return 
StaxUtils.read(getClass().getResourceAsStream(resourcePath));
-        } catch (XMLStreamException e) {
+        try (InputStream is = getClass().getResourceAsStream(resourcePath)) {
+            return StaxUtils.read(is);
+        } catch (XMLStreamException | IOException e) {
             throw new RuntimeException(e);
         }
     }
diff --git 
a/rt/javascript/javascript-rt/src/main/resources/org/apache/cxf/javascript/cxf-utils.js
 
b/rt/javascript/javascript-rt/src/main/resources/org/apache/cxf/javascript/cxf-utils.js
index 46d8864f356..cbf74f5b694 100644
--- 
a/rt/javascript/javascript-rt/src/main/resources/org/apache/cxf/javascript/cxf-utils.js
+++ 
b/rt/javascript/javascript-rt/src/main/resources/org/apache/cxf/javascript/cxf-utils.js
@@ -540,7 +540,7 @@ function org_apache_cxf_pad_string(string, len, pad, type) {
        pad = typeof(pad) == 'string' ? pad : ' ';
 
        if (type == org_apache_cxf_pad_string_PAD_BOTH) {
-               string = org_apache_cxf_pad_sring(Math.floor(len / 2) + 
string.length,
+               string = org_apache_cxf_pad_string(Math.floor(len / 2) + 
string.length,
                                pad, org_apache_cxf_pad_string_PAD_LEFT);
                return (org_apache_cxf_pad_string(Math.ceil(len / 2) + 
string.length,
                                pad, org_apache_cxf_pad_string_PAD_RIGHT));
diff --git 
a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientImpl.java 
b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientImpl.java
index 48f5b9947ce..a6ed934d270 100644
--- 
a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientImpl.java
+++ 
b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/ClientImpl.java
@@ -67,6 +67,7 @@ public class ClientImpl implements Client {
     private Configurable<Client> configImpl;
     private TLSConfiguration secConfig;
     private boolean closed;
+    private final Object baseClientsLock = new Object();
     private Set<WebClient> baseClients =
         Collections.synchronizedSet(Collections.newSetFromMap(new 
WeakHashMap<WebClient, Boolean>()));
 
@@ -78,16 +79,15 @@ public class ClientImpl implements Client {
 
     @Override
     public void close() {
-        if (!closed) {
-            synchronized (baseClients) {
+        synchronized (baseClientsLock) {
+            if (!closed) {
                 for (WebClient wc : baseClients) {
                     wc.close();
                 }
+                baseClients = null;
+                closed = true;
             }
-            baseClients = null;
-            closed = true;
         }
-
     }
 
     @Override
diff --git 
a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractContentEncryptionAlgorithm.java
 
b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractContentEncryptionAlgorithm.java
index 21ae4c70ea0..a5a46d4fb5d 100644
--- 
a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractContentEncryptionAlgorithm.java
+++ 
b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractContentEncryptionAlgorithm.java
@@ -51,24 +51,24 @@ public abstract class AbstractContentEncryptionAlgorithm 
extends AbstractContent
 
     public byte[] getContentEncryptionKey(JweHeaders headers) {
         final byte[] theCek;
-        if (cek == null) {
-            String algoJava = getAlgorithm().getJavaName();
-            SecretKey secretKey = 
CryptoUtils.getSecretKey(AlgorithmUtils.stripAlgoProperties(algoJava),
-                          getContentEncryptionKeySize(headers));
-            theCek = secretKey.getEncoded();
-            if (generateCekOnce) {
-                synchronized (this) {
+        synchronized (this) {
+            if (cek == null) {
+                String algoJava = getAlgorithm().getJavaName();
+                SecretKey secretKey = 
CryptoUtils.getSecretKey(AlgorithmUtils.stripAlgoProperties(algoJava),
+                              getContentEncryptionKeySize(headers));
+                theCek = secretKey.getEncoded();
+                if (generateCekOnce) {
                     cek = theCek;
                 }
+                // Clean the key after we're done with it
+                try {
+                    secretKey.destroy();
+                } catch (DestroyFailedException e) {
+                    // ignore
+                }
+            } else {
+                theCek = cek;
             }
-            // Clean the key after we're done with it
-            try {
-                secretKey.destroy();
-            } catch (DestroyFailedException e) {
-                // ignore
-            }
-        } else {
-            theCek = cek;
         }
         return theCek;
     }
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/CodeAuthSupplier.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/CodeAuthSupplier.java
index efca0ee42c3..b923e9f5095 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/CodeAuthSupplier.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/CodeAuthSupplier.java
@@ -42,16 +42,14 @@ public class CodeAuthSupplier implements HttpAuthSupplier {
                                    URI currentURI,
                                    Message message,
                                    String fullHeader) {
-        if (code != null) {
-            synchronized (tokenSupplier) {
-                if (tokenSupplier.getClientAccessToken().getTokenKey() == 
null) {
-                    WebClient wc = 
tokenSupplier.createAccessTokenServiceClient();
-                    ClientAccessToken at = OAuthClientUtils.getAccessToken(wc,
-                                                    
tokenSupplier.getConsumer(),
-                                                    new 
AuthorizationCodeGrant(code));
-                    code = null;
-                    tokenSupplier.setClientAccessToken(at);
-                }
+        synchronized (tokenSupplier) {
+            if (code != null && 
tokenSupplier.getClientAccessToken().getTokenKey() == null) {
+                WebClient wc = tokenSupplier.createAccessTokenServiceClient();
+                ClientAccessToken at = OAuthClientUtils.getAccessToken(wc,
+                                                tokenSupplier.getConsumer(),
+                                                new 
AuthorizationCodeGrant(code));
+                code = null;
+                tokenSupplier.setClientAccessToken(at);
             }
         }
         return tokenSupplier.getAuthorization(authPolicy, currentURI, message, 
fullHeader);
diff --git 
a/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/CXFServlet.java
 
b/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/CXFServlet.java
index d8e3f26b280..a64da06e7ee 100644
--- 
a/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/CXFServlet.java
+++ 
b/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/CXFServlet.java
@@ -61,10 +61,8 @@ public class CXFServlet extends CXFNonSpringServlet
 
         String configLocation = 
servletConfig.getInitParameter("config-location");
         if (configLocation == null) {
-            try {
-                InputStream is = 
servletConfig.getServletContext().getResourceAsStream("/WEB-INF/cxf-servlet.xml");
+            try (InputStream is = 
servletConfig.getServletContext().getResourceAsStream("/WEB-INF/cxf-servlet.xml"))
 {
                 if (is != null && is.available() > 0) {
-                    is.close();
                     configLocation = "/WEB-INF/cxf-servlet.xml";
                 }
             } catch (Exception ex) {
diff --git 
a/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java
 
b/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java
index cff4311be29..9e133429851 100644
--- 
a/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java
+++ 
b/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java
@@ -84,8 +84,10 @@ public class ServiceListGeneratorServlet extends HttpServlet 
{
         if ("HEAD".equals(request.getMethod())) {
             return;
         }
-        if (bus == null) {
-            bus = BusFactory.getDefaultBus(false);
+        synchronized (this) {
+            if (bus == null) {
+                bus = BusFactory.getDefaultBus(false);
+            }
         }
         final ServiceListWriter serviceListWriter;
         if ("false".equals(request.getParameter("formatted"))) {

Reply via email to