Uncaught AssertionError from CopybookParser.parseTree on copybooks with duplicated clauses (8 crash paths, JVM -ea independent)
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 54/100
Hướng nghiên cứu
Start with ParserVisitor.scala at visitGroup and visitPrimitive (the issue identifies lines 506–509 and 796–800), then inspect the grammar rules that admit repeated clauses. Add parser tests for the listed duplicate clauses and for the duplicated SIGN control case. Done means malformed copybooks produce SyntaxErrorException consistently with and without JVM assertions enabled.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Describe the bug
CopybookParser.parseTree(...) — the public parser entry point used by the spark-cobol data source — throws an uncaught java.lang.AssertionError when a copybook contains a duplicated clause on the same data entry (e.g. two PICTURE, two OCCURS, two REDEFINES, duplicate VALUE).
- Class: CWE-617 (Reachable Assertion). Availability impact only (no memory-safety).
- Affected:
za.co.absa.cobrix:cobol-parser_2.13:2.11.2(Maven Central latest, 2026-10-12); the same asserts are still onmaster@ 2026-10-23 at the same lines. - Always-on: the crash is not a debug-only invariant failure — it fires with the default JVM flags (
-da) too.
Three factors combine:
- The ANTLR grammar admits any number of these clauses (
( ... )*repetition), so the invalid input passes syntax validation and reaches the visitor. - The visitor enforces its "at most one / exactly one" invariants only with
scala.Predef.assert(ParserVisitor.scalaL506–509visitGroup; L796–800visitPrimitive). No semantic check rejects duplicates with the library's ownSyntaxErrorException. scala.Predef.assertis@elidable(ASSERTION)and the published artifact has the calls compiled in, so they fire regardless of-ea/-da. Nothing catches between the visitor and the public API, so theErrorescapesparseTree(...).
Confirmed crash paths (all deterministic, identical with and without -ea — 8 crash paths × 2 modes = 16/16; row 5 is the control, see below):
| # | data entry | duplicated clause | result | failure location |
|---|---|---|---|---|
| 1 | primitive | PIC X(2) PIC X(5) |
AssertionError |
visitPrimitive :800 |
| 2 | primitive | COMP COMP-3 (USAGE ×2) |
AssertionError |
visitPrimitive :797 |
| 3 | primitive | OCCURS 2 TIMES OCCURS 3 TIMES |
AssertionError |
visitPrimitive :798 |
| 4 | primitive | REDEFINES FOO REDEFINES BAR |
AssertionError |
visitPrimitive :796 |
| 5 | primitive | SIGN LEADING SEPARATE SIGN TRAILING SEPARATE | SyntaxErrorException (control — grammar rejects, every tested flavor) | — (:799 assert unreachable) |
| 6 | group | REDEFINES A1 REDEFINES A2 |
AssertionError |
visitGroup :506 |
| 7 | group | COMP-3 PACKED-DECIMAL (usageGroup ×2) |
AssertionError |
visitGroup :507 |
| 8 | group | OCCURS 2 TIMES OCCURS 3 TIMES |
AssertionError |
visitGroup :508 |
| 9 | group | VALUE 'A' VALUE 'B' |
AssertionError |
visitGroup :509 |
Row 5 is the control: duplicated SIGN clauses are rejected with the library's intended error
type (SyntaxErrorException) in every flavor tested — adjacent, with SEPARATE CHARACTER,
reversed order, SIGN IS form, with another clause in between, and triple — in both -ea
and default JVM modes. It shows the error model that the other 8 paths bypass, and makes
the :799 (ctx.separateSign.size() < 2) assert unreachable from the accepted language —
that dead assert can be fixed or dropped together with the others.
Escape path / stack:
java.lang.AssertionError: assertion failed
at scala.Predef$.assert(Predef.scala:264)
at za.co.absa.cobrix.cobol.parser.antlr.ParserVisitor.visitPrimitive(ParserVisitor.scala:800)
at za.co.absa.cobrix.cobol.parser.antlr.copybookParser$PrimitiveContext.accept(copybookParser.java:3559)
...
at za.co.absa.cobrix.cobol.parser.antlr.ANTLRParser$.parse(ANTLRParser.scala:88)
at za.co.absa.cobrix.cobol.parser.CopybookParser$.parseTree(CopybookParser.scala:336)
Found by coverage-guided fuzzing (Jazzer 0.30 around parseTree) and minimized. A plain java.lang.Error aborts the calling Spark job, and re-reading the same input re-crashes deterministically (no retry tolerance).
Code snippet that caused the issue
import za.co.absa.cobrix.cobol.parser.CopybookParser
// duplicated PICTURE clause on one data entry (row 1)
val copybook =
""" 01 REC1.
| 05 MES PIC X(2) PIC X(5).
|""".stripMargin
CopybookParser.parseTree(copybook)
// java.lang.AssertionError: assertion failed
// at za.co.absa.cobrix.cobol.parser.antlr.ParserVisitor.visitPrimitive(ParserVisitor.scala:800)
Reachable the same way from Spark:
spark.read
.format("cobol")
.option("copybook_contents", copybook) // copybook with a duplicated clause
.load(path)
The other 7 crash cases from the table (rows 2–4 and 6–9; each is a single duplicated clause) all reproduce identically — e.g. 05 F PIC X COMP COMP-3., 05 G PIC 9 OCCURS 2 TIMES OCCURS 3 TIMES., 05 A REDEFINES X REDEFINES Y., group-level REDEFINES/usage/OCCURS/VALUE duplicates, etc. A standalone Java probe covering all 9 cases was used (runs only against the published Maven artifacts, no rebuild).
Expected behavior
A malformed copybook should be rejected with the library's own za.co.absa.cobrix.cobol.parser.exceptions.SyntaxErrorException (as already happens for genuine syntax errors via the ANTLR error listener, and for semantic errors such as in checkBounds), with a clear message like "duplicate clause X on data entry Y" — not an uncaught java.lang.AssertionError.
The behaviour must be identical with and without -ea.
Context
- Cobrix version:
za.co.absa.cobrix:cobol-parser_2.13:2.11.2(Maven Central latest, published 2026-10-12); same issue onmaster@ 2026-10-23 - Spark version: n/a for the standalone repro (parser-level); also reachable via
spark-cobol - Scala version: 2.13.18 (
scala-library; artifact built for 2.13) - Operating system: Linux x86_64 (OpenJDK 21.0.13 Temurin)
CVSS v3.1 (suggested, copybook from a not-fully-trusted feed): AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H → 6.5 (Medium).
Copybook (if possible)
(rows 6–9: each line is its own one-entry copybook; the error fires on the line the probe focuses on — shown together for compactness)
Primary crashing copybook (realistic multi-field layout; note 10 MES carries two PICTURE clauses):
01 MESSAGE.
05 MESCAGE-TOP.
10 MESSAGE-TYPE PIC X(2).
10 MES PIC X PIC X(1).
10 MESSAGE-DATA PIC X(10).
Minimal header-only group variants (rows 6–9):
01 R.
05 A REDEFINES X REDEFINES Y.
05 B COMP-3 PACKED-DECIMAL.
05 C OCCURS 2 TIMES OCCURS 3 TIMES.
05 D VALUE 'A' VALUE 'B'.
Attachments: standalone probe PocAssertFamily.java (9 cases, prints crash location per case), full probe output for -ea and -da (identical for the 8 crash cases, 16/16), and the fuzzer crash input + Java reproducer. Data file is not needed to reproduce (the crash is parse-level and data-independent), but a small one can be attached if useful.
poc_results.txt
PocAssertFamily.java
Crash_cc10fa3d5bfb9296bd39fee83dd200380925f302.java
crash-cc10fa3d5bfb9296bd39fee83dd200380925f302.txt
- Ngôn ngữ chính
- Scala
- Star
- 170
- Fork
- 96
- Merge trung bình
- 7 ngày 5 giờ
- Pull request đã merge (30 ngày)
- 4
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của AbsaOSS/cobrix
-
enhancement
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
-
question
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 38/100
-
question
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 42/100
-
Low Values in Binary DataĐang mởquestion
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
-
enhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
Tất cả issue của AbsaOSS/cobrix
Issue tương tự
-
requires-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
apache/datafusion-comet#7583 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
A-api C-bug S-ready-for-human
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
ergoplatform/ergo#2932 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
lichess-org/lila#22454 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
chipsalliance/rocket-chip#3845 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100