From 82268799abded7711cf9d3ea55401f46a2554df1 Mon Sep 17 00:00:00 2001 From: eazi201 Date: Tue, 4 Feb 2025 11:39:53 +0200 Subject: [PATCH] Attempt to fix logText progressive memory issue in LargeText.java --- core/pom.xml | 6 ++++ .../hudson/console/AnnotatedLargeText.java | 32 ++++++++++++++----- .../java/hudson/util/ChunkedInputStream.java | 6 ++++ 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 4c49c99bf807..a0e54f858013 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -250,6 +250,12 @@ THE SOFTWARE. org.connectbot jbcrypt + + org.eclipse.jetty + jetty-server + 9.4.51.v20230217 + compile + org.fusesource.jansi diff --git a/core/src/main/java/hudson/console/AnnotatedLargeText.java b/core/src/main/java/hudson/console/AnnotatedLargeText.java index 963435afe1ae..35d5641c10d6 100644 --- a/core/src/main/java/hudson/console/AnnotatedLargeText.java +++ b/core/src/main/java/hudson/console/AnnotatedLargeText.java @@ -197,16 +197,20 @@ private ConsoleAnnotator createAnnotator(StaplerRequest2 req) throws IOExcept private ConsoleAnnotator getConsoleAnnotator(ObjectInputStream ois) throws IOException, ClassNotFoundException { return (ConsoleAnnotator) ois.readObject(); } - @CheckReturnValue @Override public long writeLogTo(long start, Writer w) throws IOException { - if (isHtml()) + if (isHtml()) { return writeHtmlTo(start, w); - else - return super.writeLogTo(start, w); + } + + long bytesRead = super.writeLogTo(start, w); + w.flush(); + + return bytesRead; } + /** * Strips annotations using a {@link PlainTextConsoleOutputStream}. * {@inheritDoc} @@ -231,17 +235,29 @@ public long writeHtmlTo(long start, Writer w) throws IOException { ConsoleAnnotationOutputStream caw = new ConsoleAnnotationOutputStream<>( w, createAnnotator(Stapler.getCurrentRequest2()), context, charset); long r = super.writeLogTo(start, caw); + long bytesRead = 0; + + try (Writer writer = w) { + bytesRead = super.writeLogTo(start, writer); + writer.flush(); + } ByteArrayOutputStream baos = new ByteArrayOutputStream(); Cipher sym = PASSING_ANNOTATOR.encrypt(); - ObjectOutputStream oos = AnonymousClassWarnings.checkingObjectOutputStream(new GZIPOutputStream(new CipherOutputStream(baos, sym))); - oos.writeLong(System.currentTimeMillis()); // send timestamp to prevent a replay attack + ObjectOutputStream oos = AnonymousClassWarnings.checkingObjectOutputStream( + new GZIPOutputStream(new CipherOutputStream(baos, sym)) + ); + + oos.writeLong(System.currentTimeMillis()); oos.writeObject(caw.getConsoleAnnotator()); oos.close(); + StaplerResponse2 rsp = Stapler.getCurrentResponse2(); - if (rsp != null) + if (rsp != null) { rsp.setHeader("X-ConsoleAnnotator", Base64.getEncoder().encodeToString(baos.toByteArray())); - return r; + } + + return bytesRead; } /** diff --git a/core/src/main/java/hudson/util/ChunkedInputStream.java b/core/src/main/java/hudson/util/ChunkedInputStream.java index cfe61a17fcf1..f4fff97bfe19 100644 --- a/core/src/main/java/hudson/util/ChunkedInputStream.java +++ b/core/src/main/java/hudson/util/ChunkedInputStream.java @@ -134,6 +134,9 @@ public int read(byte[] b, int off, int len) throws IOException { len = Math.min(len, chunkSize - pos); int count = in.read(b, off, len); pos += count; + if (pos >= chunkSize) { + in.skip(2); + } return count; } @@ -273,6 +276,9 @@ private static int getChunkSizeFromInputStream(final InputStream in) } catch (NumberFormatException e) { throw new IOException("Bad chunk size: " + dataString, e); } + if (result > 10 * 1024 * 1024) { + throw new IOException("Chunk size too large: " + result); + } return result; }