Skip to content

Fix panic on a row whose cells are not in ascending column order - #2376

Merged
xuri merged 4 commits into
qax-os:masterfrom
arpitjain099:fix/checkrow-out-of-order-columns
Aug 16, 2026
Merged

Fix panic on a row whose cells are not in ascending column order#2376
xuri merged 4 commits into
qax-os:masterfrom
arpitjain099:fix/checkrow-out-of-order-columns

Conversation

@arpitjain099

Copy link
Copy Markdown
Contributor

Fixes the panic reported in GHSA-8mcq-6wmr-jrjv.

checkRow reads lastCol from the last element of the row and sizes the rebuilt slice from it, then scatters every cell into that slice by the cell's own column reference. Cells are not guaranteed to be stored in ascending column order, so when an earlier cell names a higher column than the final element, the write goes past the end.

A row holding Z1 followed by C1 has colCount 2 and lastCol 3, so the branch is entered, three placeholders are created, and Z1 is then written to index 25:

panic: runtime error: index out of range [25] with length 3

This is reachable from the ordinary read APIs, since checkRow runs on worksheet load, so opening a crafted file and calling GetCellValue is enough.

The change takes the maximum column across the row rather than reading the last element. The existing loop above already tracks a running maximum for filling in missing r attributes, but that value is not used here.

Added TestCheckRowOutOfOrderColumns to rows_test.go. It covers the direct checkRow call and a read through GetCellValue. It panics with the message above on the current code and passes with the change. go test ./... is green.

checkRow takes lastCol from the last element of the row, then scatters every
cell into the rebuilt slice by that cell's own column reference. Cells are not
guaranteed to be stored in ascending column order, so when an earlier cell
names a higher column than the final element, the write lands past the end.

A row of Z1 followed by C1 gives a length of 3 and a write to index 25:

    panic: runtime error: index out of range [25] with length 3

Take the maximum column across the row instead of reading the last element.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
@codecov

codecov Bot commented Aug 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.62%. Comparing base (be7a163) to head (b2a91db).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2376   +/-   ##
=======================================
  Coverage   99.62%   99.62%           
=======================================
  Files          32       32           
  Lines       27004    27005    +1     
=======================================
+ Hits        26902    26905    +3     
+ Misses         53       52    -1     
+ Partials       49       48    -1     
Flag Coverage Δ
unittests 99.62% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@xuri xuri added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Aug 15, 2026

@xuri xuri 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.

Thanks for your pull request. I've left some comments.

Comment thread rows_test.go Outdated
Comment thread rows.go Outdated
Comment thread rows.go Outdated
arpitjain099 and others added 3 commits August 15, 2026 21:07
Addresses review feedback.

Folds the maximum-column search into the loop that already walks the
row's cells to fill in missing r attributes, instead of adding a second
pass. That removes the extra CellNameToCoordinates call per cell, so the
only added work is two integer comparisons.

It also drops the CellNameToCoordinates on the last element, whose error
branch was never reachable: the loop above already returns for any cell
whose r attribute fails to parse, and the r values it generates are always
valid. A full-suite coverage profile on master shows that branch at 0.

Test now stores raw sheet XML through f.Pkg rather than a deserialized
xlsxWorksheet, matching how the other sheet-parsing tests set up input.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>

@xuri xuri 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.

Thanks for your contribution. I've made some changes based on your branch.

@xuri
xuri merged commit 46a5eb2 into qax-os:master Aug 16, 2026
21 checks passed
@xuri xuri added this to v2.11.1 Aug 17, 2026
@xuri xuri moved this to Security in v2.11.1 Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

Status: Security

Development

Successfully merging this pull request may close these issues.

2 participants