Skip to content

Commit f448767

Browse files
craig[bot]yuzefovich
andcommitted
Merge #151159
151159: sql: fix a crash with `crdb_internal.execute_internally` in an edge case r=yuzefovich a=yuzefovich A recent thread reminded me of an issue we discovered a year ago in a support ticket https://github.com/cockroachlabs/support/issues/2954 where we could crash a node with SHOW COMMIT TIMESTAMP when run via `crdb_internal.execute_internally` builtin. It was a mistake that when I added this builtin, I prohibited stmts that have `Ack` return type: the goal was to prohibit stmts that modify txn state, which are marked with `TCL` stmt type. We already included this properly in the SQL shell API, but it was missing for the builtin, and this is now fixed. I considered only using TCL as the prohibition marker, but after reviewing stmts that have Ack return type and are not TCL, I found only one (TRUNCATE) that seems useful to allow whereas others (like AlterTenant..., Cursor-related) could be problematic, so I kept the Ack as prohibition marker and added an exception for TRUNCATE. Two spots where we check this are now unified. Epic: None Release note: None Co-authored-by: Yahor Yuzefovich <[email protected]>
2 parents b328729 + 59b9555 commit f448767

File tree

4 files changed

+27
-12
lines changed

4 files changed

+27
-12
lines changed

pkg/server/api_v2_sql.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -472,12 +472,7 @@ func (a *apiV2Server) execSQL(w http.ResponseWriter, r *http.Request) {
472472
}
473473
}()
474474

475-
if returnType == tree.Ack || stmt.stmt.AST.StatementType() == tree.TypeTCL {
476-
// We want to disallow statements that modify txn state (like
477-
// BEGIN and COMMIT) because the internal executor does not
478-
// expect such statements. We'll lean on the safe side and
479-
// prohibit all statements with an ACK return type, similar
480-
// to the builtin `crdb_internal.execute_internally(...)`.
475+
if !tree.UserStmtAllowedForInternalExecutor(stmt.stmt.AST) {
481476
return errors.New("disallowed statement type")
482477
}
483478

pkg/sql/opt/exec/execbuilder/testdata/execute_internally_builtin

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ SELECT crdb_internal.execute_internally('SELECT k FROM t;', true);
2424
3
2525
5
2626

27+
statement ok
28+
SELECT crdb_internal.execute_internally('TRUNCATE t;', true);
29+
30+
query empty
31+
SELECT crdb_internal.execute_internally('SELECT k FROM t;', true);
32+
2733
# Set the database via the override.
2834
query T rowsort
2935
SELECT crdb_internal.execute_internally('EXPLAIN SELECT k FROM t;', 'Database=test');
@@ -281,3 +287,7 @@ SELECT crdb_internal.execute_internally('SHOW disallow_full_table_scans;', true)
281287
off
282288

283289
subtest end
290+
291+
# Regression test for crashing with SHOW COMMIT TIMESTAMP.
292+
statement error this statement is disallowed
293+
SELECT crdb_internal.execute_internally('SHOW COMMIT TIMESTAMP;', true);

pkg/sql/sem/builtins/generator_builtins.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4068,12 +4068,7 @@ func makeInternallyExecutedQueryGeneratorOverload(
40684068
if len(stmts) != 1 {
40694069
return nil, errors.Newf("only one statement is supported, %d were given", len(stmts))
40704070
}
4071-
if stmts[0].AST.StatementReturnType() == tree.Ack {
4072-
// We want to disallow statements that modify txn state (like
4073-
// BEGIN and COMMIT). Such statements (as well as some others
4074-
// like changing cluster settings and dealing with prepared
4075-
// statements) have the Ack return type, so we'll lean on the
4076-
// safe side and prohibit them all.
4071+
if !tree.UserStmtAllowedForInternalExecutor(stmts[0].AST) {
40774072
return nil, errors.New("this statement is disallowed")
40784073
}
40794074
var sessionBound bool

pkg/sql/sem/tree/stmt.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,22 @@ func ReturnsAtMostOneRow(stmt Statement) bool {
206206
return true
207207
}
208208
return false
209+
}
209210

211+
// UserStmtAllowedForInternalExecutor returns whether the user-provided stmt is
212+
// allowed to be executed via the internal executor.
213+
func UserStmtAllowedForInternalExecutor(stmt Statement) bool {
214+
if stmt.StatementType() == TypeTCL || stmt.StatementReturnType() == Ack {
215+
// We need to disallow stmts that modify txn state (i.e. TCL) since the
216+
// internal executor doesn't support them.
217+
//
218+
// Additionally, out of caution, we disallow stmts that have the Ack
219+
// return type (which include some AlterTenant*, Cursor-related, and a
220+
// few others). The only exception that seems nice to allow is TRUNCATE.
221+
_, isTruncate := stmt.(*Truncate)
222+
return isTruncate
223+
}
224+
return true
210225
}
211226

212227
// HiddenFromShowQueries is a pseudo-interface to be implemented

0 commit comments

Comments
 (0)