Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8361637

Missing sub-int value validation in the Class-File API

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Unresolved
    • Icon: P4 P4
    • 26
    • core-libs
    • None
    • behavioral
    • low
    • Some users may have already started passing out-of-bounds values and live with latent failures. They will now get exceptions, which is a behavioral change.
    • Java API
    • SE

      Summary

      In the Class-File API, add IllegalArgumentException to methods that accept user-supplied int to truncate to more narrow data formats.

      Problem

      The Class-File API has many methods that accept user-supplied int values to construct class-file constructs that store more narrow values as u2/u1 (unsigned 2/1 byte). Users currently can pass in out-of-bound values, such as negative values, and they are silently truncated upon writing. They create live data models that are considered different but would be identical once written to class files, and many of these out of range values indicate silent overflows that should have been caught eagerly for program integrity.

      Solution

      Convert these APIs so they throw IllegalArgumentException whenever they receive an out-of-bounds input. An exception is made for ClassFileVersion::minorVersion, which has a convention of using -1 for 65535, the minor version with all bits set, to indicate preview class files.

      Alternative solutions considered include simply performing active truncation so data models would be identical in the views as read from class files; this approach is rejected because these overflow values overwhelmingly indicate program errors that should have been caught eagerly.

      The most common data are flag values and indices into lists. In both cases, eager failure almost always seem better.

      Specification

      The specification patch is attached. Here is the list of APIs changed, ignoring overloads:

      java.lang.classfile:

      • ClassBuilder::withVersion
      • ClassBuilder::withFlags
      • ClassBuilder::withField
      • ClassBuilder::withMethod
      • ClassBuilder::withMethodBody
      • ClassFileVersion::of
      • CodeBuilder::lineNumber
      • CodeBuilder::characterRange
      • FieldBuilder::withFlags
      • MethodBuilder::withFlags
      • TypeAnnotation.TargetInfo::ofParameter
      • TypeAnnotation.TargetInfo::ofClassTypeParameter
      • TypeAnnotation.TargetInfo::ofMethodTypeParameter
      • TypeAnnotation.TargetInfo::ofClassExtends
      • TypeAnnotation.TargetInfo::ofTypeParameterBound
      • TypeAnnotation.TargetInfo::ofClassTypeParameterBound
      • TypeAnnotation.TargetInfo::ofMethodTypeParameterBound
      • TypeAnnotation.TargetInfo::ofMethodFormalParameter
      • TypeAnnotation.TargetInfo::ofThrows
      • TypeAnnotation.TargetInfo::ofExceptionParameter
      • TypeAnnotation.TargetInfo::ofTypeArgument
      • TypeAnnotation.TargetInfo::ofCastExpr
      • TypeAnnotation.TargetInfo::ofConstructorInvocationTypeArgument
      • TypeAnnotation.TargetInfo::ofMethodInvocationTypeArgument
      • TypeAnnotation.TargetInfo::ofConstructorReferenceTypeArgument
      • TypeAnnotation.TargetInfo::ofMethodReferenceTypeArgument
      • TypeAnnotation.LocalVarTargetInfo::of
      • TypeAnnotation.TypePathComponent::of

      attribute:

      • CharacterRangeInfo::of
      • InnerClassInfo::of
      • LineNumberInfo::of
      • MethodParameterInfo::of
      • MethodParameterInfo::ofParameter
      • ModuleAttribute::of
      • ModuleAttribute.ModuleAttributeBuilder::moduleFlags
      • ModuleExportInfo::of
      • ModuleOpenInfo::of
      • ModuleRequireInfo::of
      • ModuleResolutionAttribute::of

      constantpool:

      • ConstantPoolBuilder::methodHandleEntry

      instruction:

      • CharacterRange::of
      • LineNumber::of

      Additional package level documentation changes:

      --- a/src/java.base/share/classes/java/lang/classfile/package-info.java
      +++ b/src/java.base/share/classes/java/lang/classfile/package-info.java
      @@ -273,13 +273,22 @@
        * accepting constant pool entries.
        *
        * <h3>Consistency checks, syntax checks and verification</h3>
      + * The Class-File API performs checks to ensure arguments are representable in
      + * the {@code class} file format.  A value that is lost when it is built to a
      + * {@code class} file and re-parsed to a model is rejected with an {@link
      + * IllegalArgumentException}.  For example, a negative value or a value over
      + * {@code 65535} is lost when built to a {@code u2} (JVMS {@jvms 4}) item, with
      + * the range {@code [0, 65535]}.  In particular, any variable-sized table
      + * exceeding its maximum representable size is rejected.
      + * <p>
        * No consistency checks are performed while building or transforming classfiles
      - * (except for null arguments checks). All builders and classfile elements factory
      - * methods accepts the provided information without implicit validation.
      - * However, fatal inconsistencies (like for example invalid code sequence or
      + * (except for null and representable arguments checks). All builders and
      + * classfile elements factory methods accepts the provided information without
      + * implicit validation, as long as they are representable in the {@code class}
      + * file format.  However, fatal inconsistencies (like invalid code sequence or
        * unresolved labels) affects internal tools and may cause exceptions later in
        * the classfile building process.  These fatal exceptions are thrown as
      - * {@link IllegalArgumentException}.
      + * {@code IllegalArgumentException}.
        * <p>
        * Using nominal descriptors assures the right serial form is applied by the
        * ClassFile API library based on the actual context. Also these nominal
      @@ -294,9 +303,9 @@
        * <p>
        * On the other hand it is possible to use builders methods and factories accepting
        * constant pool entries directly. Constant pool entries can be constructed also
      - * directly from raw values, with no additional conversions or validations.
      - * Following example uses intentionally wrong class name form and it is applied
      - * without any validation or conversion.
      + * directly from raw values, with no additional conversions or validations, as
      + * long as they are representable.  Following example uses intentionally wrong
      + * class name form, which is applied without any validation or conversion.
        * {@snippet lang=java :
        * var invalidClassEntry = constantPoolBuilder.classEntry(
        *                             constantPoolBuilder.utf8Entry("mypackage.MyClass"));

            liach Chen Liang
            liach Chen Liang
            Adam Sotona
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: