Skip to content

Commit 4989034

Browse files
authored
Prevent cycles/stackoverflow in dump (#13230)
* Prevent cycles/stackoverflow in dump Avoid cycles and stack overflows if dump API is called directly. * updates from review
1 parent c89596a commit 4989034

File tree

2 files changed

+25
-14
lines changed

2 files changed

+25
-14
lines changed

jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ else if (o instanceof Map.Entry<?, ?> entry)
185185
*/
186186
static void dumpObjects(Appendable out, String indent, Object object, Object... extraChildren) throws IOException
187187
{
188+
out = DumpAppendable.ensure(out);
188189
dumpObject(out, object);
189190

190191
if (DumpAppendable.hasVisited(out, object))
@@ -240,6 +241,7 @@ else if (object instanceof Map)
240241

241242
static void dumpContainer(Appendable out, String indent, Container object, boolean last) throws IOException
242243
{
244+
out = DumpAppendable.ensure(out);
243245
Container container = object;
244246
ContainerLifeCycle containerLifeCycle = container instanceof ContainerLifeCycle ? (ContainerLifeCycle)container : null;
245247
for (Iterator<Object> i = container.getBeans().iterator(); i.hasNext(); )
@@ -284,6 +286,7 @@ else if (containerLifeCycle != null && containerLifeCycle.isUnmanaged(bean))
284286

285287
static void dumpIterable(Appendable out, String indent, Iterable<?> iterable, boolean last) throws IOException
286288
{
289+
out = DumpAppendable.ensure(out);
287290
for (Iterator<?> i = iterable.iterator(); i.hasNext(); )
288291
{
289292
Object item = i.next();
@@ -301,6 +304,7 @@ static void dumpIterable(Appendable out, String indent, Iterable<?> iterable, bo
301304

302305
static void dumpMapEntries(Appendable out, String indent, Map<?, ?> map, boolean last) throws IOException
303306
{
307+
out = DumpAppendable.ensure(out);
304308
for (Iterator<? extends Map.Entry<?, ?>> i = map.entrySet().iterator(); i.hasNext(); )
305309
{
306310
Map.Entry entry = i.next();

jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/component/DumpableTest.java

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
package org.eclipse.jetty.util.component;
1515

16+
import java.io.ByteArrayOutputStream;
17+
import java.io.PrintStream;
1618
import java.util.ArrayList;
1719
import java.util.Collection;
1820
import java.util.List;
@@ -50,6 +52,20 @@ public void testNonNullDumpableCollection() throws Exception
5052
@Test
5153
public void testDumpableCollectionWithCycle() throws Exception
5254
{
55+
final String EXPECTED = """
56+
A size=3
57+
+> B size=4
58+
| +> si
59+
| +> see
60+
| +> sea
61+
| +> C size=3
62+
| +> ay
63+
| +>@ A size=3
64+
| +> ai
65+
+> be
66+
+> bee
67+
""";
68+
5369
List<Object> listC = new ArrayList<>();
5470
DumpableCollection c = new DumpableCollection("C", listC);
5571
DumpableCollection b = new DumpableCollection("B", List.of("si", "see", "sea", c));
@@ -59,19 +75,10 @@ public void testDumpableCollectionWithCycle() throws Exception
5975
listC.add("ai");
6076

6177
String dump = a.dump();
62-
assertThat(dump, Matchers.startsWith("""
63-
A size=3
64-
+> B size=4
65-
| +> si
66-
| +> see
67-
| +> sea
68-
| +> C size=3
69-
| +> ay
70-
| +>@ A size=3
71-
| +> ai
72-
+> be
73-
+> bee
74-
legend: +- bean, += managed, +~ unmanaged, +? auto, +: iterable, +] array, +} map, +> pojo; @ visited
75-
JVM:"""));
78+
assertThat(dump, Matchers.startsWith(EXPECTED));
79+
80+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
81+
a.dump(new PrintStream(baos), "");
82+
assertThat(baos.toString(), Matchers.startsWith(EXPECTED));
7683
}
7784
}

0 commit comments

Comments
 (0)