This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 326ff6da5595a4132e060b5c47d60c922f417355 Author: opencode <[email protected]> AuthorDate: Thu Oct 15 11:33:42 2026 +0200 Close the descriptor stream in the digester modeler source Registry.load() opens an input stream for URL and File sources and hands it to the modeler source without retaining any reference, so the stream had to be closed by the source that consumed it. MbeansDescriptorsDigesterSource.execute() previously cast the source to InputStream and parsed it without ever closing it, relying on the underlying SAX parser to release the stream. That left the release of the resource to unspecified parser behaviour. Validate the source with an instanceof check instead of a blind cast, throwing IllegalArgumentException for anything other than an InputStream, and parse inside a try-with-resources statement so the stream is closed when the parse completes, when it fails and when an unchecked error occurs. Add unit tests that pass a close-tracking input stream through Registry.load() and assert the stream is closed after both a successful parse and a parse error, and that a non-InputStream source is rejected with IllegalArgumentException. --- .../modules/MbeansDescriptorsDigesterSource.java | 6 +- .../TestMbeansDescriptorsDigesterSource.java | 90 ++++++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java b/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java index 746a9fed53..9e271a7f2d 100644 --- a/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java +++ b/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java @@ -142,7 +142,9 @@ public class MbeansDescriptorsDigesterSource extends ModelerSource { registry = Registry.getRegistry(null); } - InputStream stream = (InputStream) source; + if (!(source instanceof InputStream stream)) { + throw new IllegalArgumentException(sm.getString("registry.invalidSource")); + } List<ManagedBean> loadedMbeans = new ArrayList<>(); synchronized (dLock) { @@ -151,7 +153,7 @@ public class MbeansDescriptorsDigesterSource extends ModelerSource { } // Process the input file to configure our registry - try { + try (stream) { // Push our registry object onto the stack digester.push(loadedMbeans); digester.parse(stream); diff --git a/test/org/apache/tomcat/util/modeler/modules/TestMbeansDescriptorsDigesterSource.java b/test/org/apache/tomcat/util/modeler/modules/TestMbeansDescriptorsDigesterSource.java new file mode 100644 index 0000000000..c512cdf2fe --- /dev/null +++ b/test/org/apache/tomcat/util/modeler/modules/TestMbeansDescriptorsDigesterSource.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.util.modeler.modules; + +import java.io.ByteArrayInputStream; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.junit.Assert; +import org.junit.Test; + +import org.apache.tomcat.util.modeler.Registry; + +public class TestMbeansDescriptorsDigesterSource { + + private static final String XML = + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<mbeans-descriptors>\n" + + " <mbean name=\"TestDigesterSourceBean\" description=\"Tester bean\" domain=\"tester\">\n" + + " <attribute name=\"value\" description=\"Tester value\" type=\"java.lang.String\"/>\n" + + " </mbean>\n</mbeans-descriptors>\n"; + + private static final String BAD_XML = "<mbeans-descriptors><invalid>"; + + private static InputStream createTrackingStream(String content, AtomicBoolean closed) { + InputStream delegate = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)); + return new FilterInputStream(delegate) { + @Override + public void close() throws IOException { + closed.set(true); + super.close(); + } + }; + } + + @Test + public void testLoadClosesStreamAfterSuccessfulParse() throws Exception { + AtomicBoolean closed = new AtomicBoolean(); + Registry registry = Registry.getRegistry(null); + + registry.load(null, createTrackingStream(XML, closed), null); + + Assert.assertTrue(closed.get()); + Assert.assertNotNull(registry.findManagedBean("TestDigesterSourceBean")); + } + + @Test + public void testLoadClosesStreamAfterParseError() throws Exception { + AtomicBoolean closed = new AtomicBoolean(); + Registry registry = Registry.getRegistry(null); + + try { + registry.load(null, createTrackingStream(BAD_XML, closed), null); + Assert.fail("Expected a parse error"); + } catch (Exception e) { + // Expected + } + + Assert.assertTrue(closed.get()); + } + + @Test + public void testExecuteRequiresInputStreamSource() throws Exception { + Registry registry = Registry.getRegistry(null); + ModelerSource source = new MbeansDescriptorsDigesterSource(); + + try { + source.loadDescriptors(registry, "tester", "not-an-input-stream"); + Assert.fail("Expected an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // Expected + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
