This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-bcel.git
The following commit(s) were added to refs/heads/master by this push: new 428b65e0 Validate the u4 length of all attributes 428b65e0 is described below commit 428b65e0d6cc0f094b428f8ab92810ad7221afe1 Author: Gary David Gregory (Code signing key) <ggreg...@apache.org> AuthorDate: Mon Nov 21 08:03:04 2022 -0500 Validate the u4 length of all attributes --- src/changes/changes.xml | 2 +- .../java/org/apache/bcel/classfile/Attribute.java | 37 ++++++++++++++++++---- .../java/org/apache/bcel/classfile/Unknown.java | 10 +----- src/main/java/org/apache/bcel/util/Args.java | 28 ++++++++++++++++ 4 files changed, 61 insertions(+), 16 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 502b818f..30a26c71 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -98,7 +98,7 @@ The <action> type attribute can be add,update,fix,remove. <action type="fix" dev="ggregory" due-to="Gary Gregory">org.apache.bcel.util.ClassPath hashCode() and equals() don't match.</action> <action type="fix" dev="markt" due-to="OSS-Fuzz">org.apache.bcel.classfile.StackMapType constructors now throw ClassFormatException on invalid input.</action> <action type="add" dev="ggregory" due-to="nbauma109, Gary Gregory">Code coverage and bug fixes for bcelifier #171.</action> - <action type="fix" dev="markt" due-to="Mark Thomas">org.apache.bcel.classfile.Unknown constructors now throw ClassFormatException on invalid length input.</action> + <action type="fix" dev="markt" due-to="Mark Thomas, Gary Gregory">org.apache.bcel.classfile.Attribute constructors now throw ClassFormatException on invalid length input.</action> <!-- UPDATE --> <action type="update" dev="ggregory" due-to="Gary Gregory">Bump spotbugs-maven-plugin from 4.7.2.2 to 4.7.3.0 #167.</action> <action type="update" dev="ggregory" due-to="Dependabot">Bump jmh.version from 1.35 to 1.36 #170.</action> diff --git a/src/main/java/org/apache/bcel/classfile/Attribute.java b/src/main/java/org/apache/bcel/classfile/Attribute.java index d1d38f40..14a76cc2 100644 --- a/src/main/java/org/apache/bcel/classfile/Attribute.java +++ b/src/main/java/org/apache/bcel/classfile/Attribute.java @@ -27,9 +27,17 @@ import org.apache.bcel.Const; import org.apache.bcel.util.Args; /** - * Abstract super class for <em>Attribute</em> objects. Currently the <em>ConstantValue</em>, <em>SourceFile</em>, - * <em>Code</em>, <em>Exceptiontable</em>, <em>LineNumberTable</em>, <em>LocalVariableTable</em>, <em>InnerClasses</em> - * and <em>Synthetic</em> attributes are supported. The <em>Unknown</em> attribute stands for non-standard-attributes. + * Abstract super class for <em>Attribute</em> objects. Currently the <em>ConstantValue</em>, <em>SourceFile</em>, <em>Code</em>, <em>Exceptiontable</em>, + * <em>LineNumberTable</em>, <em>LocalVariableTable</em>, <em>InnerClasses</em> and <em>Synthetic</em> attributes are supported. The <em>Unknown</em> attribute + * stands for non-standard-attributes. + * + * <pre> + * attribute_info { + * u2 attribute_name_index; + * u4 attribute_length; + * u1 info[attribute_length]; + * } + * </pre> * * @see ConstantValue * @see SourceFile @@ -238,10 +246,26 @@ public abstract class Attribute implements Cloneable, Node { @java.lang.Deprecated protected ConstantPool constant_pool; // TODO make private (has getter & setter) + /** + * Constructs an instance. + * + * <pre> + * attribute_info { + * u2 attribute_name_index; + * u4 attribute_length; + * u1 info[attribute_length]; + * } + * </pre> + * + * @param tag tag. + * @param nameIndex u2 name index. + * @param length u4 length. + * @param constantPool constant pool. + */ protected Attribute(final byte tag, final int nameIndex, final int length, final ConstantPool constantPool) { this.tag = tag; this.name_index = Args.requireU2(nameIndex, 0, constantPool.getLength(), getClass().getSimpleName() + " name index"); - this.length = length; + this.length = Args.requireU4(length, getClass().getSimpleName() + " attribute length"); this.constant_pool = constantPool; } @@ -271,12 +295,13 @@ public abstract class Attribute implements Cloneable, Node { } /** - * @return deep copy of this attribute + * @param constantPool constant pool to save. + * @return deep copy of this attribute. */ public abstract Attribute copy(ConstantPool constantPool); /** - * Dump attribute to file stream in binary format. + * Dumps attribute to file stream in binary format. * * @param file Output file stream * @throws IOException if an I/O error occurs. diff --git a/src/main/java/org/apache/bcel/classfile/Unknown.java b/src/main/java/org/apache/bcel/classfile/Unknown.java index df088430..6f72dc24 100644 --- a/src/main/java/org/apache/bcel/classfile/Unknown.java +++ b/src/main/java/org/apache/bcel/classfile/Unknown.java @@ -49,7 +49,7 @@ public final class Unknown extends Attribute { public Unknown(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) { super(Const.ATTR_UNKNOWN, nameIndex, length, constantPool); this.bytes = bytes; - name = constantPool.getConstantUtf8(nameIndex).getBytes(); + this.name = constantPool.getConstantUtf8(nameIndex).getBytes(); } /** @@ -66,14 +66,6 @@ public final class Unknown extends Attribute { if (length > 0) { bytes = new byte[length]; input.readFully(bytes); - } else if (length < 0) { - // Length is defined in the JVM specification as an unsigned 4 byte - // integer but is read as a signed integer. This is not an issue as - // the JRE API consistently uses byte[] or ByteBuffer for classes. - // Therefore treat any negative number here as a format error. - throw new ClassFormatException(String.format( - "Invalid length %,d for Unknown attribute. Must be greater than or equal to zero and less than %,d", - length & 0xFFFFFFFFL, Integer.MAX_VALUE)); } } diff --git a/src/main/java/org/apache/bcel/util/Args.java b/src/main/java/org/apache/bcel/util/Args.java index defc071f..642f6508 100644 --- a/src/main/java/org/apache/bcel/util/Args.java +++ b/src/main/java/org/apache/bcel/util/Args.java @@ -53,6 +53,20 @@ public class Args { return require(value, 0, message); } + /** + * Requires a u1 value. + * + * @param value The value to test. + * @param message The message prefix + * @return The value to test. + */ + public static int requireU1(final int value, final String message) { + if (value < 0 || value > Const.MAX_BYTE) { + throw new ClassFormatException(String.format("%s [Value out of range (0 - %,d) for type u1: %,d]", message, Const.MAX_BYTE, value)); + } + return value; + } + /** * Requires a u2 value of at least {@code min} and not above {@code max}. * @@ -97,4 +111,18 @@ public class Args { public static int requireU2(final int value, final String message) { return requireU2(value, 0, message); } + + /** + * Requires a u4 value. + * + * @param value The value to test. + * @param message The message prefix + * @return The value to test. + */ + public static int requireU4(final int value, final String message) { + if (value < 0) { + throw new ClassFormatException(String.format("%s [Value out of range (0 - %,d) for type u4: %,d]", message, Integer.MAX_VALUE, value)); + } + return value; + } }