mirror of
https://github.com/mikefarah/yq.git
synced 2026-09-01 14:14:52 +08:00
Fix panic on negative slice indices that underflow after adjustment (#2646)
sliceArrayOperator adjusts negative indices by adding Content length,
but does not clamp the result. When the absolute value of a negative
index exceeds Content length (e.g. .[-99999:3] on a 3-element array),
the adjusted index remains negative and causes an out-of-bounds access
in the Content slice loop.
Extract the adjust-and-clamp logic into clampSliceIndex and use it for
both index positions.
Reproducer (panics before this fix, returns full array after):
echo '[a, b, c]' | yq '.[-99999:3]'
Found by OSS-Fuzz via the lima project's FuzzEvaluateExpression target.
https://issues.oss-fuzz.com/issues/438776028
Signed-off-by: Jan Dubois <jan@jandubois.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
0374ad6b4b
commit
80139ae1cc
+17
-11
@@ -16,6 +16,21 @@ func getSliceNumber(d *dataTreeNavigator, context Context, node *CandidateNode,
|
||||
return parseInt(result.MatchingNodes.Front().Value.(*CandidateNode).Value)
|
||||
}
|
||||
|
||||
// clampSliceIndex resolves a possibly-negative slice index against
|
||||
// length and clamps the result to [0, length].
|
||||
func clampSliceIndex(index, length int) int {
|
||||
if index < 0 {
|
||||
index += length
|
||||
}
|
||||
if index < 0 {
|
||||
return 0
|
||||
}
|
||||
if index > length {
|
||||
return length
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
func sliceArrayOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
||||
log.Debug("slice array operator!")
|
||||
@@ -32,22 +47,13 @@ func sliceArrayOperator(d *dataTreeNavigator, context Context, expressionNode *E
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
relativeFirstNumber := firstNumber
|
||||
if relativeFirstNumber < 0 {
|
||||
relativeFirstNumber = len(lhsNode.Content) + firstNumber
|
||||
}
|
||||
relativeFirstNumber := clampSliceIndex(firstNumber, len(lhsNode.Content))
|
||||
|
||||
secondNumber, err := getSliceNumber(d, context, lhsNode, expressionNode.RHS)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
relativeSecondNumber := secondNumber
|
||||
if relativeSecondNumber < 0 {
|
||||
relativeSecondNumber = len(lhsNode.Content) + secondNumber
|
||||
} else if relativeSecondNumber > len(lhsNode.Content) {
|
||||
relativeSecondNumber = len(lhsNode.Content)
|
||||
}
|
||||
relativeSecondNumber := clampSliceIndex(secondNumber, len(lhsNode.Content))
|
||||
|
||||
log.Debugf("calculateIndicesToTraverse: slice from %v to %v", relativeFirstNumber, relativeSecondNumber)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user