Skip to content

Commit af6b4f3

Browse files
committed
Handle large string repeat counts on 32-bit
1 parent 8f3291d commit af6b4f3

2 files changed

Lines changed: 16 additions & 10 deletions

File tree

pkg/yqlib/operator_multiply.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,17 +150,25 @@ func repeatString(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error
150150
target := lhs.CopyWithoutContent()
151151
target.UpdateAttributesFrom(stringNode, assignPreferences{})
152152

153-
count, err := parseInt(intNode.Value)
153+
_, count, err := parseInt64(intNode.Value)
154154
if err != nil {
155155
return nil, err
156156
} else if count < 0 {
157157
return nil, fmt.Errorf("cannot repeat string by a negative number (%v)", count)
158158
}
159-
maxResultLen := 10 * 1024 * 1024 // 10 MiB
160-
if count > 0 && len(stringNode.Value) > maxResultLen/count {
159+
if stringNode.Value == "" {
160+
target.Value = ""
161+
return target, nil
162+
}
163+
maxResultLen := int64(10 * 1024 * 1024) // 10 MiB
164+
if count > 0 && int64(len(stringNode.Value)) > maxResultLen/count {
161165
return nil, fmt.Errorf("result of repeating string (%v bytes) by %v would exceed %v bytes", len(stringNode.Value), count, maxResultLen)
162166
}
163-
target.Value = strings.Repeat(stringNode.Value, count)
167+
repeatCount, err := parseInt(intNode.Value)
168+
if err != nil {
169+
return nil, err
170+
}
171+
target.Value = strings.Repeat(stringNode.Value, repeatCount)
164172

165173
return target, nil
166174
}

pkg/yqlib/operator_multiply_test.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package yqlib
22

33
import (
44
"fmt"
5-
"math/bits"
65
"strings"
76
"testing"
87
)
@@ -709,12 +708,11 @@ var multiplyOperatorScenarios = []expressionScenario{
709708
},
710709
{
711710
// Pick a count whose product with len("ab") overflows int on
712-
// any architecture: 2^30 on 32-bit, 2^62 on 64-bit. Doubling
713-
// either yields MaxInt+1, which wraps to MinInt and bypasses
714-
// a naive len*count guard.
711+
// 64-bit architectures; it must still report the repeat size
712+
// limit on 32-bit architectures instead of an int range error.
715713
skipDoc: true,
716-
expression: fmt.Sprintf(`"ab" * %d`, 1<<(bits.UintSize-2)),
717-
expectedError: fmt.Sprintf("result of repeating string (2 bytes) by %d would exceed 10485760 bytes", 1<<(bits.UintSize-2)),
714+
expression: fmt.Sprintf(`"ab" * %d`, int64(1)<<62),
715+
expectedError: fmt.Sprintf("result of repeating string (2 bytes) by %d would exceed 10485760 bytes", int64(1)<<62),
718716
},
719717
}
720718

0 commit comments

Comments
 (0)