From a58fa6e73e4594cfb0e46bdbebad48072771e5bd Mon Sep 17 00:00:00 2001 From: "Archie L. Cobbs" Date: Thu, 16 Feb 2023 14:48:39 +0000 Subject: [PATCH] 8302514: Misleading error generated when empty class file encountered Reviewed-by: vromero, jwaters --- .../com/sun/tools/javac/jvm/ClassReader.java | 35 ++++- .../sun/tools/javac/jvm/ModuleNameReader.java | 19 ++- .../com/sun/tools/javac/jvm/PoolReader.java | 41 +++++- .../tools/javac/resources/compiler.properties | 3 + .../com/sun/tools/javac/util/ArrayUtils.java | 53 +++++++- .../com/sun/tools/javac/util/ByteBuffer.java | 121 ++++++++++++++---- .../classreader/TruncatedClassFileTest.java | 119 +++++++++++++++++ .../tools/javac/diags/examples.not-yet.txt | 1 + .../tools/javac/modules/EdgeCases.java | 2 +- .../NoAbortForBadClassFile.java | 2 +- 10 files changed, 351 insertions(+), 45 deletions(-) create mode 100644 test/langtools/tools/javac/classreader/TruncatedClassFileTest.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index d47617b30ab..16ed4bea5e9 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -62,6 +62,7 @@ import com.sun.tools.javac.main.Option; import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.resources.CompilerProperties.Warnings; import com.sun.tools.javac.util.*; +import com.sun.tools.javac.util.ByteBuffer.UnderflowException; import com.sun.tools.javac.util.DefinedBy.Api; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; @@ -329,7 +330,12 @@ public class ClassReader { /** Read a character. */ char nextChar() { - char res = buf.getChar(bp); + char res; + try { + res = buf.getChar(bp); + } catch (UnderflowException e) { + throw badClassFile("bad.class.truncated.at.offset", Integer.toString(e.getLength())); + } bp += 2; return res; } @@ -337,13 +343,22 @@ public class ClassReader { /** Read a byte. */ int nextByte() { - return buf.getByte(bp++) & 0xFF; + try { + return buf.getByte(bp++) & 0xFF; + } catch (UnderflowException e) { + throw badClassFile("bad.class.truncated.at.offset", Integer.toString(e.getLength())); + } } /** Read an integer. */ int nextInt() { - int res = buf.getInt(bp); + int res; + try { + res = buf.getInt(bp); + } catch (UnderflowException e) { + throw badClassFile("bad.class.truncated.at.offset", Integer.toString(e.getLength())); + } bp += 4; return res; } @@ -1482,7 +1497,12 @@ public class ClassReader { /** Read parameter annotations. */ void readParameterAnnotations(Symbol meth) { - int numParameters = buf.getByte(bp++) & 0xFF; + int numParameters; + try { + numParameters = buf.getByte(bp++) & 0xFF; + } catch (UnderflowException e) { + throw badClassFile("bad.class.truncated.at.offset", Integer.toString(e.getLength())); + } if (parameterAnnotations == null) { parameterAnnotations = new ParameterAnnotations[numParameters]; } else if (parameterAnnotations.length != numParameters) { @@ -1771,7 +1791,12 @@ public class ClassReader { } Attribute readAttributeValue() { - char c = (char) buf.getByte(bp++); + char c; + try { + c = (char)buf.getByte(bp++); + } catch (UnderflowException e) { + throw badClassFile("bad.class.truncated.at.offset", Integer.toString(e.getLength())); + } switch (c) { case 'B': return new Attribute.Constant(syms.byteType, poolReader.getConstant(nextChar())); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java index e41d46b8dfb..a34246cabdb 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java @@ -25,6 +25,7 @@ package com.sun.tools.javac.jvm; import com.sun.tools.javac.util.ByteBuffer; +import com.sun.tools.javac.util.ByteBuffer.UnderflowException; import com.sun.tools.javac.util.Convert; import com.sun.tools.javac.util.Name.NameMapper; @@ -132,16 +133,26 @@ public class ModuleNameReader { /** Read a character. */ - char nextChar() { - char res = buf.getChar(bp); + char nextChar() throws BadClassFile { + char res; + try { + res = buf.getChar(bp); + } catch (UnderflowException e) { + throw new BadClassFile("class file truncated at offset " + e.getLength()); + } bp += 2; return res; } /** Read an integer. */ - int nextInt() { - int res = buf.getInt(bp); + int nextInt() throws BadClassFile { + int res; + try { + res = buf.getInt(bp); + } catch (UnderflowException e) { + throw new BadClassFile("class file truncated at offset " + e.getLength()); + } bp += 4; return res; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java index da33619cfb1..5607105bba3 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java @@ -32,6 +32,7 @@ import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.jvm.PoolConstant.NameAndType; import com.sun.tools.javac.util.ByteBuffer; +import com.sun.tools.javac.util.ByteBuffer.UnderflowException; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Name.NameMapper; import com.sun.tools.javac.util.Names; @@ -118,21 +119,30 @@ public class PoolReader { * Get class name without resolving */ Z peekClassName(int index, NameMapper mapper) { - return peekName(buf.getChar(pool.offset(index)), mapper); + return peekItemName(index, mapper); } /** * Get package name without resolving */ Z peekPackageName(int index, NameMapper mapper) { - return peekName(buf.getChar(pool.offset(index)), mapper); + return peekItemName(index, mapper); } /** * Get module name without resolving */ Z peekModuleName(int index, NameMapper mapper) { - return peekName(buf.getChar(pool.offset(index)), mapper); + return peekItemName(index, mapper); + } + + private Z peekItemName(int index, NameMapper mapper) { + try { + index = buf.getChar(pool.offset(index)); + } catch (UnderflowException e) { + throw reader.badClassFile("bad.class.truncated.at.offset", Integer.toString(e.getLength())); + } + return peekName(index, mapper); } /** @@ -153,7 +163,11 @@ public class PoolReader { * Peek a name from the pool at given index without resolving. */ Z peekName(int index, Name.NameMapper mapper) { - return getUtf8(index, mapper); + try { + return getUtf8(index, mapper); + } catch (UnderflowException e) { + throw reader.badClassFile("bad.class.truncated.at.offset", Integer.toString(e.getLength())); + } } /** @@ -188,7 +202,7 @@ public class PoolReader { return pool.tag(index) == tag; } - private Z getUtf8(int index, NameMapper mapper) { + private Z getUtf8(int index, NameMapper mapper) throws UnderflowException { int tag = pool.tag(index); int offset = pool.offset(index); if (tag == CONSTANT_Utf8) { @@ -201,7 +215,7 @@ public class PoolReader { } } - private Object resolve(ByteBuffer poolbuf, int tag, int offset) { + private Object resolve(ByteBuffer poolbuf, int tag, int offset) throws UnderflowException { switch (tag) { case CONSTANT_Utf8: { int len = poolbuf.getChar(offset); @@ -250,6 +264,14 @@ public class PoolReader { * {@link PoolReader#peekClassName(int, NameMapper)}. */ int readPool(ByteBuffer poolbuf, int offset) { + try { + return readPoolInternal(poolbuf, offset); + } catch (UnderflowException e) { + throw reader.badClassFile("bad.class.truncated.at.offset", Integer.toString(e.getLength())); + } + } + + private int readPoolInternal(ByteBuffer poolbuf, int offset) throws UnderflowException { int poolSize = poolbuf.getChar(offset); int index = 1; offset += 2; @@ -343,7 +365,12 @@ public class PoolReader { if (!expectedTags.get(currentTag)) { throw reader.badClassFile("unexpected.const.pool.tag.at", tag(index), offset(index)); } - P p = (P)resolve(poolbuf, tag(index), offset(index)); + P p; + try { + p = (P)resolve(poolbuf, tag(index), offset(index)); + } catch (UnderflowException e) { + throw reader.badClassFile("bad.class.truncated.at.offset", Integer.toString(e.getLength())); + } values[index] = p; return p; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index c2135c2aedb..4e20f5c6bfc 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -2431,6 +2431,9 @@ compiler.misc.bad.const.pool.tag.at=\ compiler.misc.unexpected.const.pool.tag.at=\ unexpected constant pool tag: {0} at {1} +compiler.misc.bad.class.truncated.at.offset=\ + class file truncated at offset {0} + compiler.misc.bad.signature=\ bad signature: {0} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ArrayUtils.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ArrayUtils.java index 67a02369cf9..011f18ece48 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ArrayUtils.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ArrayUtils.java @@ -35,12 +35,30 @@ import java.lang.reflect.Array; public class ArrayUtils { private static int calculateNewLength(int currentLength, int maxIndex) { - while (currentLength < maxIndex + 1) + if (maxIndex == Integer.MAX_VALUE) + maxIndex--; // avoid negative overflow + while (currentLength < maxIndex + 1) { currentLength = currentLength * 2; + if (currentLength <= 0) { // avoid infinite loop and negative overflow + currentLength = maxIndex + 1; + break; + } + } return currentLength; } + /** + * Ensure the given array has length at least {@code maxIndex + 1}. + * + * @param array original array + * @param maxIndex exclusive lower bound for desired length + * @return possibly reallocated array of length at least {@code maxIndex + 1} + * @throws NullPointerException if {@code array} is null + * @throws IllegalArgumentException if {@code maxIndex} is negative + */ public static T[] ensureCapacity(T[] array, int maxIndex) { + if (maxIndex < 0) + throw new IllegalArgumentException("maxIndex=" + maxIndex); if (maxIndex < array.length) { return array; } else { @@ -52,7 +70,18 @@ public class ArrayUtils { } } + /** + * Ensure the given array has length at least {@code maxIndex + 1}. + * + * @param array original array + * @param maxIndex exclusive lower bound for desired length + * @return possibly reallocated array of length at least {@code maxIndex + 1} + * @throws NullPointerException if {@code array} is null + * @throws IllegalArgumentException if {@code maxIndex} is negative + */ public static byte[] ensureCapacity(byte[] array, int maxIndex) { + if (maxIndex < 0) + throw new IllegalArgumentException("maxIndex=" + maxIndex); if (maxIndex < array.length) { return array; } else { @@ -63,7 +92,18 @@ public class ArrayUtils { } } + /** + * Ensure the given array has length at least {@code maxIndex + 1}. + * + * @param array original array + * @param maxIndex exclusive lower bound for desired length + * @return possibly reallocated array of length at least {@code maxIndex + 1} + * @throws NullPointerException if {@code array} is null + * @throws IllegalArgumentException if {@code maxIndex} is negative + */ public static char[] ensureCapacity(char[] array, int maxIndex) { + if (maxIndex < 0) + throw new IllegalArgumentException("maxIndex=" + maxIndex); if (maxIndex < array.length) { return array; } else { @@ -74,7 +114,18 @@ public class ArrayUtils { } } + /** + * Ensure the given array has length at least {@code maxIndex + 1}. + * + * @param array original array + * @param maxIndex exclusive lower bound for desired length + * @return possibly reallocated array of length at least {@code maxIndex + 1} + * @throws NullPointerException if {@code array} is null + * @throws IllegalArgumentException if {@code maxIndex} is negative + */ public static int[] ensureCapacity(int[] array, int maxIndex) { + if (maxIndex < 0) + throw new IllegalArgumentException("maxIndex=" + maxIndex); if (maxIndex < array.length) { return array; } else { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ByteBuffer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ByteBuffer.java index 842a42ea096..597b4f0bdbf 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ByteBuffer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ByteBuffer.java @@ -147,35 +147,42 @@ public class ByteBuffer { appendBytes(name.getByteArray(), name.getByteOffset(), name.getByteLength()); } - /** Append the content of a given input stream. + /** Append the content of a given input stream, and then close the stream. */ public void appendStream(InputStream is) throws IOException { - try { - int start = length; - int initialSize = is.available(); - elems = ArrayUtils.ensureCapacity(elems, length + initialSize); - int r = is.read(elems, start, initialSize); - int bp = start; - while (r != -1) { - bp += r; - elems = ArrayUtils.ensureCapacity(elems, bp); - r = is.read(elems, bp, elems.length - bp); - } - } finally { - try { - is.close(); - } catch (IOException e) { - /* Ignore any errors, as this stream may have already - * thrown a related exception which is the one that - * should be reported. - */ + try (InputStream input = is) { + while (true) { + + // Read another chunk of data, using size hint from available(). + // If available() is accurate, the array size should be just right. + int amountToRead = Math.max(input.available(), 64); + elems = ArrayUtils.ensureCapacity(elems, length + amountToRead); + int amountRead = input.read(elems, length, amountToRead); + if (amountRead == -1) + break; + length += amountRead; + + // Check for the common case where input.available() returned the + // entire remaining input; in that case, avoid an extra array extension. + // Note we are guaranteed that elems.length >= length + 1 at this point. + if (amountRead == amountToRead) { + int byt = input.read(); + if (byt == -1) + break; + elems[length++] = (byte)byt; + } } } } /** Extract an integer at position bp from elems. + * + * @param bp starting offset + * @throws UnderflowException if there is not enough data in this buffer + * @throws IllegalArgumentException if {@code bp} is negative */ - public int getInt(int bp) { + public int getInt(int bp) throws UnderflowException { + verifyRange(bp, 4); return ((elems[bp] & 0xFF) << 24) + ((elems[bp+1] & 0xFF) << 16) + @@ -185,8 +192,13 @@ public class ByteBuffer { /** Extract a long integer at position bp from elems. + * + * @param bp starting offset + * @throws UnderflowException if there is not enough data in this buffer + * @throws IllegalArgumentException if {@code bp} is negative */ - public long getLong(int bp) { + public long getLong(int bp) throws UnderflowException { + verifyRange(bp, 8); DataInputStream elemsin = new DataInputStream(new ByteArrayInputStream(elems, bp, 8)); try { @@ -197,8 +209,13 @@ public class ByteBuffer { } /** Extract a float at position bp from elems. + * + * @param bp starting offset + * @throws UnderflowException if there is not enough data in this buffer + * @throws IllegalArgumentException if {@code bp} is negative */ - public float getFloat(int bp) { + public float getFloat(int bp) throws UnderflowException { + verifyRange(bp, 4); DataInputStream elemsin = new DataInputStream(new ByteArrayInputStream(elems, bp, 4)); try { @@ -209,8 +226,13 @@ public class ByteBuffer { } /** Extract a double at position bp from elems. + * + * @param bp starting offset + * @throws UnderflowException if there is not enough data in this buffer + * @throws IllegalArgumentException if {@code bp} is negative */ - public double getDouble(int bp) { + public double getDouble(int bp) throws UnderflowException { + verifyRange(bp, 8); DataInputStream elemsin = new DataInputStream(new ByteArrayInputStream(elems, bp, 8)); try { @@ -221,13 +243,25 @@ public class ByteBuffer { } /** Extract a character at position bp from elems. + * + * @param bp starting offset + * @throws UnderflowException if there is not enough data in this buffer + * @throws IllegalArgumentException if {@code bp} is negative */ - public char getChar(int bp) { + public char getChar(int bp) throws UnderflowException { + verifyRange(bp, 2); return (char)(((elems[bp] & 0xFF) << 8) + (elems[bp+1] & 0xFF)); } - public byte getByte(int bp) { + /** Extract a byte at position bp from elems. + * + * @param bp starting offset + * @throws UnderflowException if there is not enough data in this buffer + * @throws IllegalArgumentException if {@code bp} is negative + */ + public byte getByte(int bp) throws UnderflowException { + verifyRange(bp, 1); return elems[bp]; } @@ -242,4 +276,39 @@ public class ByteBuffer { public Name toName(Names names) { return names.fromUtf(elems, 0, length); } + + /** Verify there are at least the specified number of bytes in this buffer at the specified offset. + * + * @param off starting offset + * @param len required length + * @throws UnderflowException if there is not enough data in this buffer + * @throws IllegalArgumentException if {@code off} or {@code len} is negative + */ + public void verifyRange(int off, int len) throws UnderflowException { + if (off < 0 || len < 0) + throw new IllegalArgumentException("off=" + off + ", len=" + len); + if (off + len < 0 || off + len > length) + throw new UnderflowException(length); + } + +// UnderflowException + + /** Thrown when trying to read past the end of the buffer. + */ + public static class UnderflowException extends Exception { + + private static final long serialVersionUID = 0; + + private final int length; + + public UnderflowException(int length) { + this.length = length; + } + + /** Get the length of the buffer, which apparently is not long enough. + */ + public int getLength() { + return length; + } + } } diff --git a/test/langtools/tools/javac/classreader/TruncatedClassFileTest.java b/test/langtools/tools/javac/classreader/TruncatedClassFileTest.java new file mode 100644 index 00000000000..f68d21c3839 --- /dev/null +++ b/test/langtools/tools/javac/classreader/TruncatedClassFileTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8302514 + * @summary Verify truncated class files are detected and reported as truncated + */ + +import com.sun.tools.javac.Main; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.file.Files; + +public class TruncatedClassFileTest { + + // We want a bunch of stuff in this file to make the classfile complicated + private static final String A_SOURCE = """ + public class ClassA { + public static final boolean z = true; + public static final byte b = 7; + public static final char c = '*'; + public static final short s = -12; + public static final int i = 123; + public static final float f = 123f; + public static final long j = 0x1234567812345678L; + public static final double d = Math.PI; + public static final String str = new String("test123"); + @SuppressWarnings("blah") + public ClassA() { + new Thread(); + } + } + """; + + // This file will get compiled against a trunctated version of A.class + private static final String B_SOURCE = """ + public class ClassB { + public ClassB() { + new ClassA(); + } + } + """; + + private static final File A_SOURCE_FILE = new File("ClassA.java"); + private static final File B_SOURCE_FILE = new File("ClassB.java"); + private static final File A_CLASS_FILE = new File("ClassA.class"); + + private static void createSourceFile(File file, String content) throws IOException { + try (PrintStream output = new PrintStream(new FileOutputStream(file))) { + output.println(content); + } + } + + public static void main(String... args) throws Exception { + + // Create A.java and B.java + createSourceFile(A_SOURCE_FILE, A_SOURCE); + createSourceFile(B_SOURCE_FILE, B_SOURCE); + + // Compile A.java + createSourceFile(A_SOURCE_FILE, A_SOURCE); + int ret = Main.compile(new String[] { A_SOURCE_FILE.toString() }); + if (ret != 0) + throw new AssertionError("compilation of " + A_SOURCE_FILE + " failed"); + A_SOURCE_FILE.delete(); + + // Read A.class + final byte[] classfile = Files.readAllBytes(A_CLASS_FILE.toPath()); + + // Now compile B.java with truncated versions of A.class + for (int length = 0; length < classfile.length; length++) { + + // Write out truncated class file A.class + try (FileOutputStream output = new FileOutputStream(A_CLASS_FILE)) { + output.write(classfile, 0, length); + } + + // Try to compile file B.java + final StringWriter diags = new StringWriter(); + final String[] params = new String[] { + "-classpath", + ".", + "-XDrawDiagnostics", + B_SOURCE_FILE.toString() + }; + ret = Main.compile(params, new PrintWriter(diags, true)); + if (ret == 0) + throw new AssertionError("compilation with truncated class file (" + length + ") succeeded?"); + final String errmsg = "compiler.misc.bad.class.truncated.at.offset: " + length; + if (!diags.toString().contains(errmsg)) + throw new AssertionError("error message not found for truncated class file (" + length + "): " + diags); + } + } +} diff --git a/test/langtools/tools/javac/diags/examples.not-yet.txt b/test/langtools/tools/javac/diags/examples.not-yet.txt index 9d1c9a2f0af..a2b0844bb05 100644 --- a/test/langtools/tools/javac/diags/examples.not-yet.txt +++ b/test/langtools/tools/javac/diags/examples.not-yet.txt @@ -45,6 +45,7 @@ compiler.err.type.var.more.than.once # UNUSED compiler.err.type.var.more.than.once.in.result # UNUSED compiler.err.unexpected.type compiler.misc.bad.class.signature # bad class file +compiler.misc.bad.class.truncated.at.offset # bad class file compiler.misc.bad.const.pool.tag # bad class file compiler.misc.bad.const.pool.tag.at # bad class file compiler.misc.unexpected.const.pool.tag.at # bad class file diff --git a/test/langtools/tools/javac/modules/EdgeCases.java b/test/langtools/tools/javac/modules/EdgeCases.java index 0262066d7b8..0dc5d02ce4a 100644 --- a/test/langtools/tools/javac/modules/EdgeCases.java +++ b/test/langtools/tools/javac/modules/EdgeCases.java @@ -381,7 +381,7 @@ public class EdgeCases extends ModuleTestBase { .getOutputLines(OutputKind.DIRECT); List expected = Arrays.asList( - "- compiler.err.cant.access: .module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.illegal.start.of.class.file))", + "- compiler.err.cant.access: .module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.bad.class.truncated.at.offset: 0))", "1 error"); if (!expected.equals(log)) { diff --git a/test/langtools/tools/javac/processing/model/completionfailure/NoAbortForBadClassFile.java b/test/langtools/tools/javac/processing/model/completionfailure/NoAbortForBadClassFile.java index bae1c069194..65029c711b0 100644 --- a/test/langtools/tools/javac/processing/model/completionfailure/NoAbortForBadClassFile.java +++ b/test/langtools/tools/javac/processing/model/completionfailure/NoAbortForBadClassFile.java @@ -102,7 +102,7 @@ public class NoAbortForBadClassFile extends TestRunner { .getOutputLines(Task.OutputKind.DIRECT); List expectedOut = Arrays.asList( - "Test.java:1:57: compiler.err.cant.access: test.Broken, (compiler.misc.bad.class.file.header: Broken.class, (compiler.misc.class.file.wrong.class: java.lang.AutoCloseable))", + "Test.java:1:57: compiler.err.cant.access: test.Broken, (compiler.misc.bad.class.file.header: Broken.class, (compiler.misc.bad.class.truncated.at.offset: 0))", "Test.java:1:73: compiler.err.cant.resolve.location.args: kindname.method, unknown, , , (compiler.misc.location: kindname.class, java.lang.String, null)", "2 errors" );