From af6b4f38b9f404a957b519e7785ba2c7e149628a Mon Sep 17 00:00:00 2001 From: cyphercodes Date: Wed, 20 May 2026 06:37:04 +0300 Subject: [PATCH] Handle large string repeat counts on 32-bit --- pkg/yqlib/operator_multiply.go | 16 ++++++++++++---- pkg/yqlib/operator_multiply_test.go | 10 ++++------ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/pkg/yqlib/operator_multiply.go b/pkg/yqlib/operator_multiply.go index 9db2c4f5..7155aa45 100644 --- a/pkg/yqlib/operator_multiply.go +++ b/pkg/yqlib/operator_multiply.go @@ -150,17 +150,25 @@ func repeatString(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error target := lhs.CopyWithoutContent() target.UpdateAttributesFrom(stringNode, assignPreferences{}) - count, err := parseInt(intNode.Value) + _, count, err := parseInt64(intNode.Value) if err != nil { return nil, err } else if count < 0 { return nil, fmt.Errorf("cannot repeat string by a negative number (%v)", count) } - maxResultLen := 10 * 1024 * 1024 // 10 MiB - if count > 0 && len(stringNode.Value) > maxResultLen/count { + if stringNode.Value == "" { + target.Value = "" + return target, nil + } + maxResultLen := int64(10 * 1024 * 1024) // 10 MiB + if count > 0 && int64(len(stringNode.Value)) > maxResultLen/count { return nil, fmt.Errorf("result of repeating string (%v bytes) by %v would exceed %v bytes", len(stringNode.Value), count, maxResultLen) } - target.Value = strings.Repeat(stringNode.Value, count) + repeatCount, err := parseInt(intNode.Value) + if err != nil { + return nil, err + } + target.Value = strings.Repeat(stringNode.Value, repeatCount) return target, nil } diff --git a/pkg/yqlib/operator_multiply_test.go b/pkg/yqlib/operator_multiply_test.go index 66256c92..558a1afe 100644 --- a/pkg/yqlib/operator_multiply_test.go +++ b/pkg/yqlib/operator_multiply_test.go @@ -2,7 +2,6 @@ package yqlib import ( "fmt" - "math/bits" "strings" "testing" ) @@ -709,12 +708,11 @@ var multiplyOperatorScenarios = []expressionScenario{ }, { // Pick a count whose product with len("ab") overflows int on - // any architecture: 2^30 on 32-bit, 2^62 on 64-bit. Doubling - // either yields MaxInt+1, which wraps to MinInt and bypasses - // a naive len*count guard. + // 64-bit architectures; it must still report the repeat size + // limit on 32-bit architectures instead of an int range error. skipDoc: true, - expression: fmt.Sprintf(`"ab" * %d`, 1<<(bits.UintSize-2)), - expectedError: fmt.Sprintf("result of repeating string (2 bytes) by %d would exceed 10485760 bytes", 1<<(bits.UintSize-2)), + expression: fmt.Sprintf(`"ab" * %d`, int64(1)<<62), + expectedError: fmt.Sprintf("result of repeating string (2 bytes) by %d would exceed 10485760 bytes", int64(1)<<62), }, }