Skip to content

Commit 7b879ef

Browse files
committed
sql: prevent stack overflow with infinite loops in test builds
We just saw a test case where we hit stack overflow when handling a DO block with an infinite loop and `tail-call-optimization-enabled` metamorphic variable happened to use `false`. In this case, it's expected behavior that we'd be hitting the stack overflow, so in order to prevent such crashes in tests, we now do a depth check (similar to trigger depth check) to error out at the depth of 10000. Additionally, this commit removes disabling DO blocks in a single test that hit this stack overflow first as well as includes a few expected errors I saw in the artifacts into the set of ignored ones. Release note: None
1 parent b136ab6 commit 7b879ef

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

pkg/compose/compare/compare/compare_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func TestCompare(t *testing.T) {
8080
configs := map[string]testConfig{
8181
"mutators": {
8282
setup: sqlsmith.Setups[sqlsmith.RandTableSetupName],
83-
opts: []sqlsmith.SmitherOption{sqlsmith.CompareMode(), sqlsmith.DisableDoBlocks()},
83+
opts: []sqlsmith.SmitherOption{sqlsmith.CompareMode()},
8484
ignoreSQLErrors: true,
8585
conns: []testConn{
8686
{

pkg/sql/routine.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry"
2323
"github.com/cockroachdb/cockroach/pkg/sql/types"
2424
"github.com/cockroachdb/cockroach/pkg/storage/enginepb"
25+
"github.com/cockroachdb/cockroach/pkg/util/buildutil"
2526
"github.com/cockroachdb/cockroach/pkg/util/metamorphic"
2627
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
2728
"github.com/cockroachdb/cockroach/pkg/util/tracing"
@@ -155,6 +156,20 @@ func (p *planner) EvalRoutineExpr(
155156
}
156157
ctx = context.WithValue(ctx, triggerDepthKey{}, triggerDepth+1)
157158
}
159+
if buildutil.CrdbTestBuild && !tailCallOptimizationEnabled {
160+
// In test builds when we disable tail-call optimization, we might hit
161+
// stack overflow with infinite loops.
162+
var routineDepth int
163+
if routineDepthValue := ctx.Value(routineDepthKey{}); routineDepthValue != nil {
164+
routineDepth = routineDepthValue.(int)
165+
}
166+
const maxDepth = 10000
167+
if routineDepth > maxDepth {
168+
return nil, pgerror.Newf(pgcode.ProgramLimitExceeded,
169+
"routine reached recursion depth limit: %d (probably infinite loop)", maxDepth)
170+
}
171+
ctx = context.WithValue(ctx, routineDepthKey{}, routineDepth+1)
172+
}
158173

159174
var g routineGenerator
160175
g.init(p, expr, args)
@@ -193,6 +208,8 @@ func (p *planner) EvalRoutineExpr(
193208

194209
type triggerDepthKey struct{}
195210

211+
type routineDepthKey struct{}
212+
196213
// RoutineExprGenerator returns an eval.ValueGenerator that produces the results
197214
// of a routine.
198215
func (p *planner) RoutineExprGenerator(

pkg/sql/tests/rsg_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,12 +641,17 @@ var ignoredErrorPatterns = []string{
641641
"BACKUP for requested time needs option 'revision_history'",
642642
"RESTORE timestamp: supplied backups do not cover requested time",
643643
"a partial index that does not contain all the rows needed to execute this query",
644+
"routine reached recursion depth limit",
645+
"RETURN cannot have a parameter in a procedure",
646+
"is not a known variable",
647+
"could not produce a query plan conforming to the",
644648

645649
// Numeric conditions
646650
"exponent out of range",
647651
"result out of range",
648652
"argument out of range",
649653
"integer out of range",
654+
"OID out of range",
650655
"invalid operation",
651656
"invalid mask",
652657
"cannot take square root of a negative number",
@@ -680,7 +685,8 @@ var ignoredErrorPatterns = []string{
680685
"unrecognized privilege",
681686
"invalid escape string",
682687
"error parsing regexp",
683-
"could not parse .* as type bytes",
688+
"could not parse",
689+
"error parsing EWKB",
684690
"UUID must be exactly 16 bytes long",
685691
"unsupported timespan",
686692
"does not exist",

0 commit comments

Comments
 (0)