Fix panics in GetConditionalFormats on malformed conditional formatting rules - #2375
Merged
Merged
Conversation
The cellIs, colorScale and dataBar extractors read sub-elements of a cfRule straight out of the worksheet XML and index them without checking length, and in one case without checking for nil. A workbook whose rule is missing a child that a file written by Excel would always have panics the call, so any service that opens an untrusted spreadsheet and reads its conditional formats can be crashed by a small file. Four guards, one per reachable sink: - extractCondFmtCellIs indexed Formula[0] in the fallback branch. The branch above handles exactly two formulas; a rule with none reached an empty slice. - extractCondFmtColorScale took len(c.ColorScale.Cfvo) with ColorScale nil when the cfRule has no colorScale child. - The three-colour branch of the same function was gated on the colour count alone, then indexed Cfvo[1] and Cfvo[2], so three colours with one cfvo panicked. This one is not in the report that prompted the fix; it turned up while writing the tests. - extractCondFmtDataBar guarded only c.DataBar != nil, which says nothing about the length of Cfvo or Color, so an empty dataBar element reached all three indexes. Each guard leaves the surrounding behaviour alone: a rule missing its children now yields the zero value for those fields rather than stopping the caller. Tests build four minimal workbooks and drive them through the public OpenReader and GetConditionalFormats, so they exercise the same path a caller would. All four panic without this change. Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2375 +/- ##
=======================================
Coverage 99.62% 99.62%
=======================================
Files 32 32
Lines 27001 27004 +3
=======================================
+ Hits 26899 26902 +3
Misses 53 53
Partials 49 49
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
xuri
approved these changes
Aug 12, 2026
xuri
left a comment
Member
There was a problem hiding this comment.
Thanks for your contribution. I've made some changes based on your branch for simplify unit tests code.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix for
GHSA-rxcj-4pj5-74gr. Thanks for asking for the PR.What panics
GetConditionalFormatsreaches three extractors that indexcfRulesub-elements straight out of the worksheet XML, without checking length and in one case without checking for nil. A workbook whose rule is missing a child that Excel would always write panics the call, so a service that opens an untrusted spreadsheet and reads its conditional formats can be crashed by a small file.Four sinks, all in
styles.go:extractCondFmtCellIscellIsrule with no<formula>, indexingFormula[0]on an empty sliceextractCondFmtColorScalecolorScalerule with no<colorScale>child, soc.ColorScaleis nilcolors == 3<color>elements and one<cfvo>, indexingCfvo[1]andCfvo[2]extractCondFmtDataBarc.DataBar != nil<dataBar></dataBar>, indexingCfvo[0],Cfvo[1]andColor[0]The third one is not in the advisory. It turned up while writing the tests: that branch is gated on the colour count and then indexes the cfvo slice, so the two counts can disagree. Worth fixing in the same pass.
The change
Four guards, eleven lines in
styles.go. Each one leaves the surrounding behaviour alone: a rule missing its children now yields the zero value for those fields rather than stopping the caller. No signature changes and no new error returns, so this is not a breaking change for anyone whose files are well formed.Tests
Four cases appended to
styles_test.go. Each builds a minimal workbook in memory witharchive/zip, opens it with the publicOpenReaderand callsGetConditionalFormats, so they drive the same path a caller does rather than reaching into internals.Verified individually, since a panic takes the test binary down and would otherwise mask the later cases:
With the change, all four pass and the full suite is green:
gofmtandgo vetare clean.Happy to split the third fix into its own commit or PR if you would rather keep the advisory scope exact.