Skip to content

Pack200: enforce strict attribute layout parsing - #747

Merged
garydgregory merged 21 commits into
masterfrom
fix/attribute-layout-parser
Nov 17, 2025
Merged

Pack200: enforce strict attribute layout parsing#747
garydgregory merged 21 commits into
masterfrom
fix/attribute-layout-parser

Conversation

@ppkarwasz

@ppkarwasz ppkarwasz commented Nov 11, 2025

Copy link
Copy Markdown
Member

The parser for the Pack200 attribute layout definitions micro-language was previously overly permissive, allowing invalid layouts and masking archive corruption.

This change implements strict parsing in accordance with the Java 11 version of the Pack200 specification and removes duplication of the micro-language parsing logic between pack200.NewAttributeBands and unpack200.NewAttributeBands.

The parser for the [Pack200 attribute layout definitions](https://docs.oracle.com/en/java/javase/11/docs/specs/pack-spec.html#attribute-layout-definitions) micro-language was previously overly permissive, allowing invalid layouts and masking archive corruption.

This change implements strict parsing in accordance with the [Java 11 specification](https://docs.oracle.com/en/java/javase/11/docs/specs/pack-spec.html) and removes duplication of the micro-language parsing logic between `pack200.NewAttributeBands` and `unpack200.NewAttributeBands`.

@ppkarwasz ppkarwasz left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stricter validation introduced by the parser caused several tests to fail.

Rather than relaxing the parser to match potentially incorrect test expectations, each failing test was reviewed individually, and the specific issues are described below.

// @formatter:off
final CPUTF8 layout = new CPUTF8(
"[NH[(1)]][RSH NH[RUH(1)]][TB(66,67,73,83,90)[KIH](68)[KDH](70)[KFH](74)[KJH](99)[RSH](101)[RSH RUH](115)[RUH](91)[NH[(0)]](64)[RSH[RUH(0)]]()[]]"
"[NH[(1)]][RSHNH[RUH(1)]][TB(66,67,73,83,90)[KIH](68)[KDH](70)[KFH](74)[KJH](99)[RSH](101)[RSHRUH](115)[RUH](91)[NH[(0)]](64)[RSHNH[RUH(0)]]()[]]"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test string originates from Harmony (commit b1ecf0b).

The embedded spaces are invalid per the Pack200 attribute layout specification, and the nested [...] callables are also non-conforming.

In the native implementation (see parseLayout), an unknown symbol triggers a parse failure, whereas our previous implementation incorrectly interpreted it as end-of-input.

final CPUTF8 name = new CPUTF8("");
final CPUTF8 layout = new CPUTF8("[");
assertDoesNotThrow(() -> new NewAttributeBands(1, null, null,
assertThrows(Pack200Exception.class, () -> new NewAttributeBands(1, null, null,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into the cause of this failing test:

  • The native parseLayout implementation (see reference above) treats EOF as equivalent to a closing bracket ].
  • On the other hand, I wasn't able to use the JDK 11 Java implementation to parse this example: it failed even before reaching attribute layouts,
  • Given that COMPRESS-626 specifically aims to ensure that unmatched brackets do not lead to OOM conditions and that the behavior of the C and Java implementations differ on this one, I think that this change is acceptable.

Comment on lines 31 to +33
final CPUTF8 layout = new CPUTF8("Re\\T");
assertDoesNotThrow(() -> new NewAttributeBands(1, null, null,
new AttributeDefinitionBands.AttributeDefinition(35, AttributeDefinitionBands.CONTEXT_CLASS, name, layout)));
assertThrows(Pack200Exception.class, () -> new NewAttributeBands(1, null, null, new AttributeDefinitionBands.AttributeDefinition(35,
AttributeDefinitionBands.CONTEXT_CLASS, name, layout)));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

COMPRESS-628 was also about an OOM, so the change in behavior should not be relevant.

The native C implementation should also fail on the first unrecognized letter (e).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements strict parsing for Pack200 attribute layout definitions according to the Java 11 specification. The parser now properly validates layout syntax and rejects invalid or corrupted archives that were previously accepted.

Key changes:

  • Introduced new shared parsing logic in AttributeLayoutParser and AttributeLayoutUtils classes to eliminate code duplication between pack200 and unpack200 implementations
  • Added validation for integral, reference, and other layout tags with proper error handling
  • Updated tests to expect exceptions for previously accepted invalid layouts

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/main/java/org/apache/commons/compress/harmony/internal/AttributeLayoutParser.java New parser implementation for attribute layout definitions with strict validation
src/main/java/org/apache/commons/compress/harmony/internal/AttributeLayoutUtils.java Utility methods for validating layout tags and processing layout elements
src/main/java/org/apache/commons/compress/harmony/internal/package-info.java Package documentation for new internal package
src/main/java/org/apache/commons/compress/harmony/unpack200/NewAttributeBands.java Refactored to use new shared parser, removed duplicate parsing logic
src/main/java/org/apache/commons/compress/harmony/pack200/NewAttributeBands.java Refactored to use new shared parser, removed duplicate parsing logic
src/test/java/org/apache/commons/compress/harmony/unpack200/NewAttributeBandsTest.java Added tests for empty body validation and corrected layout strings
src/test/java/org/apache/commons/compress/harmony/pack200/NewAttributeBandsTest.java Corrected layout strings to remove invalid whitespace
src/test/java/org/apache/commons/compress/harmony/pack200/Compress628Test.java Updated to expect Pack200Exception for invalid layout
src/test/java/org/apache/commons/compress/harmony/pack200/Compress626Test.java Updated to expect Pack200Exception for invalid layout
src/test/java/org/apache/commons/compress/harmony/internal/AttributeLayoutUtilsTest.java New tests for utility validation methods
src/test/java/org/apache/commons/compress/harmony/internal/AttributeLayoutParserTest.java New comprehensive parser tests for valid and invalid layouts
src/main/java/org/apache/commons/compress/harmony/archive/internal/nls/package-info.java Enhanced package documentation
pom.xml Updated OSGi and module configuration to exclude internal packages from exports
src/changes/changes.xml Added changelog entry
Comments suppressed due to low confidence (2)

src/main/java/org/apache/commons/compress/harmony/internal/AttributeLayoutUtils.java:185

  • @param tag ">" does not match any actual parameter of method "readAttributeLayout()".
     * @param <ALE>> the type of AttributeLayoutElement.

src/main/java/org/apache/commons/compress/harmony/internal/AttributeLayoutUtils.java:213

  • @param tag ">" does not match any actual parameter of method "readBody()".
     * @param <ALE>> the type of AttributeLayoutElement.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@garydgregory

Copy link
Copy Markdown
Member

Ah, we're missing a continue-on-error: ${{ matrix.experimental }} in our workflow it seems.

@ppkarwasz

Copy link
Copy Markdown
Member Author

Ah, we're missing a continue-on-error: ${{ matrix.experimental }} in our workflow it seems.

No, the macos-13 runners are just being phased off. See apache/commons-csv#591 on how to migrate to macos-latest.

The regular need to upgrade workflows to:

  • Fix problems with some runners,
  • Add and remove Java version to the matrix.

is the reason why I would prefer to have reusable workflows. The Maven build of different Commons projects is not so different.

@garydgregory

Copy link
Copy Markdown
Member

Ah, right, I remember holding off on migrating Compress to macos-latest while the IO branch was still open to avoid possible conflicts. Fixed now.

@garydgregory garydgregory left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ppkarwasz

Thank you for the PR. A few comments here and there. Note that Lang has an IntegerRange to use instead of Range<Integer>.

@ppkarwasz
ppkarwasz marked this pull request as draft November 13, 2025 09:45
This change adds a limit to the nesting level of `layout_element`s (64). Since all standard attribute layouts have a nesting level lower than 3, the limit should be suitable for most purposes.
@ppkarwasz
ppkarwasz marked this pull request as ready for review November 16, 2025 21:40
@ppkarwasz

Copy link
Copy Markdown
Member Author

@garydgregory

I’ve applied your review suggestions and also made a small refactoring to eliminate a potential infinite recursion in the parser. The parser should now be ready for another review pass.

@garydgregory
garydgregory merged commit e78e02c into master Nov 17, 2025
19 checks passed
@garydgregory
garydgregory deleted the fix/attribute-layout-parser branch November 17, 2025 11:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants