Summary
newWrappedSchemaFromAnySdkSchema wraps its input unconditionally:
// public/formulation/wrappers.go:747
func newWrappedSchemaFromAnySdkSchema(inner anysdk.Schema) Schema {
return &wrappedSchema{inner: inner}
}
When inner is nil, the caller receives a non-nil *wrappedSchema whose methods dereference the nil inner. Downstream nil checks (if col.GetSchema() != nil { ... }) pass, and the first method call panics:
panic: runtime error: invalid memory address or nil pointer dereference
github.com/stackql/any-sdk/public/formulation.(*wrappedSchema).GetType(...)
public/formulation/wrappers.go:1378
github.com/stackql/stackql/internal/stackql/drm.(*staticDRMConfig).GenerateSelectDML(...)
internal/stackql/drm/drm_cfg.go:725
Repro (via stackql v0.10.605, clickhouse provider v26.08.00442)
EXEC clickhouse.services.services.update_password
@serviceId = '<uuid>'
@@json = '{"newPasswordHash": "x", "newDoubleSha1Hash": "y"}';
Crashes before any HTTP call, while assembling the EXEC result-set DML. The method's 200 response schema is a plain object (status, requestId, result.password); during tabulation at least one column resolves a nil schema, which gets wrapped and later dereferenced.
Proposed fix
Preserve nilness in the wrapper factory:
func newWrappedSchemaFromAnySdkSchema(inner anysdk.Schema) Schema {
if inner == nil {
return nil
}
return &wrappedSchema{inner: inner}
}
Since anysdk.Schema is itself an interface, a typed-nil passed as inner would still slip through; either normalize at the producers or add a reflect-based nil check here. The same audit applies to the sibling wrapper factories in wrappers.go (wrapped method/analysis outputs) which follow the same unconditional-wrap pattern.
A sibling issue in stackql/stackql tracks the user-visible EXEC panic and a defensive check at the drm call site.
Summary
newWrappedSchemaFromAnySdkSchemawraps its input unconditionally:When
inneris nil, the caller receives a non-nil*wrappedSchemawhose methods dereference the nil inner. Downstream nil checks (if col.GetSchema() != nil { ... }) pass, and the first method call panics:Repro (via stackql v0.10.605, clickhouse provider v26.08.00442)
Crashes before any HTTP call, while assembling the EXEC result-set DML. The method's 200 response schema is a plain object (
status,requestId,result.password); during tabulation at least one column resolves a nil schema, which gets wrapped and later dereferenced.Proposed fix
Preserve nilness in the wrapper factory:
Since
anysdk.Schemais itself an interface, a typed-nil passed asinnerwould still slip through; either normalize at the producers or add a reflect-based nil check here. The same audit applies to the sibling wrapper factories inwrappers.go(wrapped method/analysis outputs) which follow the same unconditional-wrap pattern.A sibling issue in stackql/stackql tracks the user-visible EXEC panic and a defensive check at the drm call site.