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

markt-asf pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 2d240a37384b4b372c5a0490129c3156a545b6d4
Author: Mark Thomas <[email protected]>
AuthorDate: Thu Nov 5 20:50:14 2026 +0000

    Fix backport
---
 java/org/apache/jasper/compiler/SmapUtil.java     | 46 +++++++++++++++++------
 test/org/apache/jasper/compiler/TestSmapUtil.java |  7 ++--
 2 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/java/org/apache/jasper/compiler/SmapUtil.java 
b/java/org/apache/jasper/compiler/SmapUtil.java
index 16fc20f319..8f216716d8 100644
--- a/java/org/apache/jasper/compiler/SmapUtil.java
+++ b/java/org/apache/jasper/compiler/SmapUtil.java
@@ -16,8 +16,8 @@
  */
 package org.apache.jasper.compiler;
 
-import java.io.ByteArrayOutputStream;
 import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
 import java.io.EOFException;
 import java.io.File;
@@ -31,7 +31,6 @@ import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -459,6 +458,8 @@ public class SmapUtil {
 
         private static final int MAGIC = 0xCAFEBABE;
 
+        private static final int READ_CHUNK_SIZE = 8192;
+
         private static final byte[] SMAP_HEADER_BYTES = 
SMAP_HEADER.getBytes(StandardCharsets.ISO_8859_1);
 
         private final DataInputStream in;
@@ -506,10 +507,7 @@ public class SmapUtil {
                 int nameIndex = in.readUnsignedShort();
                 int len = readLength();
                 if (sdeIndexes.contains(Integer.valueOf(nameIndex))) {
-                    byte[] sde = in.readNBytes(len);
-                    if (sde.length != len) {
-                        throw new EOFException();
-                    }
+                    byte[] sde = readBytes(len);
                     if (isSmap(sde)) {
                         smap = sde;
                     }
@@ -521,8 +519,16 @@ public class SmapUtil {
         }
 
         private static boolean isSmap(byte[] sde) {
-            return sde.length >= SMAP_HEADER_BYTES.length &&
-                    Arrays.equals(sde, 0, SMAP_HEADER_BYTES.length, 
SMAP_HEADER_BYTES, 0, SMAP_HEADER_BYTES.length);
+            if (sde.length < SMAP_HEADER_BYTES.length) {
+                return false;
+            }
+            // Arrays.equals() with ranges is not available in all supported 
Java versions
+            for (int i = 0; i < SMAP_HEADER_BYTES.length; i++) {
+                if (sde[i] != SMAP_HEADER_BYTES[i]) {
+                    return false;
+                }
+            }
+            return true;
         }
 
         /*
@@ -565,10 +571,7 @@ public class SmapUtil {
                     case 1: // Utf8
                         int len = in.readUnsignedShort();
                         if (len == SDEInstaller.nameSDE.length()) {
-                            byte[] utf8 = in.readNBytes(len);
-                            if (utf8.length != len) {
-                                throw new EOFException();
-                            }
+                            byte[] utf8 = readBytes(len);
                             if (SDEInstaller.nameSDE.equals(new String(utf8, 
StandardCharsets.UTF_8))) {
                                 sdeIndexes.add(Integer.valueOf(i));
                             }
@@ -583,6 +586,25 @@ public class SmapUtil {
             return sdeIndexes;
         }
 
+        /*
+         * Reads exactly the requested number of bytes or throws an 
EOFException if the end of the stream is reached
+         * first. InputStream.readNBytes() is not used as it is not available 
in all supported Java versions. The length
+         * comes from the class file so the data is read in chunks rather than 
allocating an array of that size up
+         * front, which a corrupt length could make very large.
+         */
+        private byte[] readBytes(int count) throws IOException {
+            byte[] chunk = new byte[Math.min(count, READ_CHUNK_SIZE)];
+            ByteArrayOutputStream out = new 
ByteArrayOutputStream(chunk.length);
+            int remaining = count;
+            while (remaining > 0) {
+                int toRead = Math.min(remaining, chunk.length);
+                in.readFully(chunk, 0, toRead);
+                out.write(chunk, 0, toRead);
+                remaining -= toRead;
+            }
+            return out.toByteArray();
+        }
+
         /*
          * Skips exactly the requested number of bytes. 
InputStream.skipNBytes() is not used as it is not available in
          * all supported Java versions and InputStream.skip() may skip fewer 
bytes than requested.
diff --git a/test/org/apache/jasper/compiler/TestSmapUtil.java 
b/test/org/apache/jasper/compiler/TestSmapUtil.java
index 85d207e679..dddd716820 100644
--- a/test/org/apache/jasper/compiler/TestSmapUtil.java
+++ b/test/org/apache/jasper/compiler/TestSmapUtil.java
@@ -26,8 +26,8 @@ import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -185,7 +185,8 @@ public class TestSmapUtil extends TomcatBaseTest {
     @Test
     public void testLoadSmapNotAClassFile() throws Exception {
         File dir = createDir();
-        Files.writeString(new File(dir, "Test.class").toPath(), "CAFEBABE 
junk\n" + SMAP, StandardCharsets.ISO_8859_1);
+        Files.write(new File(dir, "Test.class").toPath(),
+                ("CAFEBABE junk\n" + 
SMAP).getBytes(StandardCharsets.ISO_8859_1));
 
         Assert.assertNull(SmapUtil.loadSmap("Test", loader(dir)));
     }
@@ -215,7 +216,7 @@ public class TestSmapUtil extends TomcatBaseTest {
         stratum.setClassFileName(file.getAbsolutePath());
         stratum.addFile("ERRORS.SMAP");
         stratum.addLineData(1, "ERRORS.SMAP", 4, 120, 1);
-        SmapUtil.installSmap(Map.of("Test", stratum));
+        SmapUtil.installSmap(Collections.singletonMap("Test", stratum));
 
         SmapStratum loaded = SmapUtil.loadSmap("Test", loader(dir));
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to