Skip to content

[Bug]: position delete mask wraps row ordinals past MaxInt64 instead of erroring #30431

Closed

Description

@iamlinjunhong

Branch Name

main

Commit ID

b24d1b3

Other Environment Information

  • Hardware parameters: Apple Silicon (arm64), standalone unit test (no mo-service needed)
  • OS type: Darwin 24.5.0 arm64, go1.27.1
  • Others: package pkg/sql/colexec/icebergdelete, production caller pkg/sql/colexec/external/iceberg_delete_apply.go:154

Actual Behavior

ApplyState.ApplyPositionMask (pkg/sql/colexec/icebergdelete/delete_apply.go:244) iterates batch rows as rowOrdinal := startRowOrdinal + int64(i) with no overflow check, and the exported helper RowOrdinals (delete_apply.go:281) does the same. With startRowOrdinal = math.MaxInt64-1 and 3 rows:

ordinals=[9223372036854775806 9223372036854775807 -9223372036854775808]
mask over wrapped range returned keep=[false false true] without error

The third row is probed as -9223372036854775808, which can never match the position index (PositionIndex.Add rejects negative ordinals), so the mask silently keeps going instead of reporting corrupt input. On the scan path (applyIcebergDeletes calls this for every batch with IcebergBatchStartRowOrdinal), wrapped ordinals mean position deletes are silently skipped for the affected rows (extra rows returned) rather than failing fast with a clear error. This is the read-path counterpart of the write-path synthesis overflow already reported separately (that one is in pkg/sql/iceberg/dml_matched_batch.go); the root cause here is independent code in the delete-apply package with its own fix location.

Expected Behavior

ApplyPositionMask (and RowOrdinals) must detect that startRowOrdinal + rowCount - 1 overflows int64 and return an error (consistent with the package's fail-fast stance elsewhere, e.g. CheckMemoryLimit, and with the writer-side Pos < 0 rejection in pkg/iceberg/dml/delete_writer.go:328), instead of probing wrapped negative ordinals.

Steps to Reproduce

Run the regression test added in this workspace (file pkg/sql/colexec/icebergdelete/loom_test_position_mask_overflow_test.go):

export CGO_CFLAGS="-I$PWD/cgo -I$PWD/thirdparties/install/include"
export CGO_LDFLAGS="-Wl,-rpath,$PWD/thirdparties/install/lib -Wl,-rpath,$PWD/cgo -L$PWD/thirdparties/install/lib -L$PWD/cgo -lmo -lusearch_c -lm"
go test -tags matrixone_test -short -count=1 ./pkg/sql/colexec/icebergdelete/ -run 'TestLoomPositionMaskRejectsRowOrdinalOverflow' -v

The test asserts RowOrdinals(math.MaxInt64-1, 3) is monotonic/non-negative and that ApplyPositionMask over a range crossing MaxInt64 returns an error. It currently fails on both counts. All 8 pre-existing tests in the package pass.

Additional information

The ordinal chain feeding this function also uses plain addition without validation: parquetRowGroupStartOrdinals (pkg/sql/colexec/external/parquet.go:156, next += rowGroup.NumRows()), batchStartOrdinal := r.h.rowOrdinalBase + r.h.offset (pkg/sql/colexec/external/reader_parquet.go:76). With honest metadata the values stay small, so this only triggers on corrupt/lying row-group counts — hence minor severity — but when it triggers, the failure mode is silent wrong results (skipped deletes) instead of an error. Suggested fix: overflow-check startRowOrdinal + int64(rowCount-1) up front in ApplyPositionMask (and in RowOrdinals).

Note: gh CLI authentication was unavailable in this test environment, so issue deduplication could only be done from local knowledge; no duplicate found locally.

Found by Loom bug hunt (module: custom-e69df17185; tests: unit, white-box, end-to-end)

Activity

  1. XuPeng-SH commented on Oct 18, 2026

    @XuPeng-SH
    Contributor

    continue20 独立功能验证(2026-10-19),修复 PR #30449。

    实测main完整SHA:2508ce7029b03e6bb3ac0bd8e66a994d12593664;Linux/amd64,Go1.27.1,CPU/CGo。复用同SHA的已构建原生产物并经仓库mo-cgo-test入口验证;隔离worktree,诊断测试通过Go overlay加入,未修改产品源代码。

    完整icebergdelete包normal/race通过。原报告MaxInt64-1、count=3与负ordinal均拒绝,返回ICEBERG_METADATA_INVALID且不返回部分mask/ordinals;补充MaxInt64精确边界、空batch以及无部分profile副作用的失败路径均通过。ApplyPositionMask、RowOrdinals、validatePositionRowOrdinalRange本轮函数语句覆盖均100%。这是损坏metadata的内部边界契约;未伪称通过正常SQL构造了不诚实的MaxInt64行组。

    原始证据目录 /workspace/work/pr-audit-continue20:iceberg-blockio-normal.log、iceberg-blockio-race.log、original-repro.log、original-repro-race.log;coverage/original-repro.out,每组.exit均0。命令包括 .agents/skills/mo-dev/scripts/mo-cgo-test -p 1 -count=1 -v -timeout=10m ./pkg/sql/colexec/icebergdelete ./pkg/vm/engine/tae/blockio(normal含coverprofile,race另加-race);公开SQL为 MO_TEST_CLUSTER_TCP_ONLY=1 .agents/skills/mo-dev/scripts/mo-cgo-test -overlay=/workspace/work/pr-audit-continue20/public-overlay.json -p 1 -v -count=1 -timeout=15m -run '^TestAudit20PublicMatrix$' ./pkg/tests/issues,扩展S3与scalar警告各有独立选择和日志。具体命令/选择范围及覆盖文件随证据保留;没有把其他未选用例当成执行。

    main报告范围通过,转 @Ariznawlll 测试,移除原开发指派。 本条不表示最近100个PR全部高覆盖实测完成。

  2. Ariznawlll commented on Oct 19, 2026

    @Ariznawlll
    Collaborator

    测试版本

    • 分支:官方 main
    • commit:2ad1d7e5c2baafdee0b8fa097ce02ca32feb3a7b;修复 PR #30449 的 merge commit 7b911aea687455af8788af07eb65952f1eda5796 已核对包含在该 SHA。
    • 部署方式:macOS/arm64 隔离 worktree、Go 1.27.1,仓库 mo-cgo-test 入口执行 pkg/sql/colexec/icebergdelete;本问题触发条件是损坏/不诚实的内部 metadata 中接近 MaxInt64 的行序号,正常 SQL 无法构造,不将 1 CN 服务查询冒充该边界验证。
    • 测试日期:2026-10-19(UTC)。

    原问题验证

    原 startRowOrdinal=MaxInt64-1,count=3 的 RowOrdinals 与 ApplyPositionMask 路径,聚焦 TestPositionDeleteRejectsOverflowedRowOrdinals 普通模式 -count=3、race 模式 -count=3 均通过:两者返回 ICEBERG_METADATA_INVALID,不会把溢出后的负序号当成未删除行继续执行;失败时返回的 ordinals/mask 为 nil,不泄漏部分结果。

    Happy Path 覆盖

    边界正好截止 MaxInt64(起点 MaxInt64-1、count=2)仍合法,ordinals 为这两个非负值,已索引的两行均被删除掩码标记。完整 icebergdelete 包普通测试本轮通过。

    Unhappy Path 覆盖

    超过 MaxInt64 的三行范围与负起点 -1 均返回同类 metadata 错误及 nil 结果;前者无静默 wrap/跳过删除,失败原子性由无部分 mask/ordinals 验证。

    白盒验证

    聚焦测试使用 -p 1 -count=3 和 -race -p 1 -count=3 分别通过;完整包普通模式 -count=1 通过。此项是内部损坏 metadata 的错误路径,未声称通过普通 Parquet SQL 生成了不诚实的超大行组。

    回归测试

    修复 PR 的 pkg/sql/colexec/icebergdelete/delete_apply_test.go 已覆盖原溢出、负起点及恰好到 MaxInt64 的对照。按回归分层,此类内部-only metadata 错误断言保留在 MatrixOne Go UT;无法用确定性的公开 SQL 触发同一不诚实 metadata,故没有向 MOTR 写入伪成功用例,也未运行 big-data/chaos。

    测试证据

    上述测试文件和修复 PR #30449 可复核确切断言及合入记录;本轮三个定向测试循环及一次完整包均 exit 0。

    测试结论

    测试通过。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

kind/bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions