Skip to content

Commit aa69d8b

Browse files
committed
fixed panic by variadic for checkConstFetchNullSafety
1 parent c9ca8e5 commit aa69d8b

File tree

2 files changed

+47
-9
lines changed

2 files changed

+47
-9
lines changed

src/linter/block.go

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,27 +1028,35 @@ func (b *blockWalker) handleIssetDimFetch(e *ir.ArrayDimFetchExpr) {
10281028
}
10291029

10301030
func (b *blockWalker) checkNullSafetyCallArgsF(args []ir.Node, fn meta.FuncInfo) {
1031+
if fn.Params == nil || fn.Name == "" {
1032+
return
1033+
}
1034+
haveVariadic := enoughArgs(args, fn)
1035+
10311036
for i, arg := range args {
1037+
if arg == nil {
1038+
continue
1039+
}
10321040
switch a := arg.(*ir.Argument).Expr.(type) {
10331041
case *ir.SimpleVar:
1034-
b.checkSimpleVarNullSafety(arg, fn, i, a)
1042+
// b.checkSimpleVarNullSafety(arg, fn, i, a, haveVariadic)
10351043

10361044
case *ir.ConstFetchExpr:
1037-
b.checkConstFetchNullSafety(arg, fn, i, a)
1045+
b.checkConstFetchNullSafety(arg, fn, i, a, haveVariadic)
10381046

10391047
case *ir.ArrayDimFetchExpr:
1040-
b.checkArrayDimFetchNullSafety(arg, fn, i, a)
1048+
// b.checkArrayDimFetchNullSafety(arg, fn, i, a, haveVariadic)
10411049

10421050
case *ir.ListExpr:
1043-
b.checkListExprNullSafety(arg, fn, i, a)
1051+
b.checkListExprNullSafety(arg, fn, i, a, haveVariadic)
10441052

10451053
case *ir.PropertyFetchExpr:
10461054
b.checkPropertyFetchNullSafety(a)
10471055
}
10481056
}
10491057
}
10501058

1051-
func (b *blockWalker) checkSimpleVarNullSafety(arg ir.Node, fn meta.FuncInfo, paramIndex int, variable *ir.SimpleVar) {
1059+
func (b *blockWalker) checkSimpleVarNullSafety(arg ir.Node, fn meta.FuncInfo, paramIndex int, variable *ir.SimpleVar, haveVariadic bool) {
10521060
varInfo, ok := b.ctx.sc.GetVar(variable)
10531061

10541062
if !ok {
@@ -1063,18 +1071,38 @@ func (b *blockWalker) checkSimpleVarNullSafety(arg ir.Node, fn meta.FuncInfo, pa
10631071
}
10641072
}
10651073

1066-
func (b *blockWalker) checkConstFetchNullSafety(arg ir.Node, fn meta.FuncInfo, paramIndex int, constExpr *ir.ConstFetchExpr) {
1074+
func (b *blockWalker) checkConstFetchNullSafety(arg ir.Node, fn meta.FuncInfo, paramIndex int, constExpr *ir.ConstFetchExpr, haveVariadic bool) {
10671075
constVal := constExpr.Constant.Value
10681076
isNull := constVal == "null"
10691077

1078+
if haveVariadic {
1079+
// If the parameter is outside the declared parameters, we check the latter as a variable
1080+
if paramIndex >= len(fn.Params)-1 {
1081+
lastParam := fn.Params[len(fn.Params)-1] // last param (variadic ...args)
1082+
if types.IsTypeMixed(lastParam.Typ) {
1083+
return
1084+
}
1085+
1086+
paramAllowsNull := types.IsTypeNullable(lastParam.Typ)
1087+
if isNull && !paramAllowsNull {
1088+
b.report(arg, LevelError, "notNullSafety",
1089+
"null passed to non-nullable variadic parameter %s in function %s",
1090+
lastParam.Name, fn.Name)
1091+
}
1092+
return
1093+
}
1094+
}
1095+
10701096
paramAllowsNull := types.IsTypeNullable(fn.Params[paramIndex].Typ)
10711097
if isNull && !paramAllowsNull {
1072-
b.report(arg, LevelError, "notNullSafety", "null passed to non-nullable parameter %s in function %s", fn.Params[paramIndex].Name, fn.Name)
1098+
b.report(arg, LevelError, "notNullSafety",
1099+
"null passed to non-nullable parameter %s in function %s",
1100+
fn.Params[paramIndex].Name, fn.Name)
10731101
}
10741102
}
10751103

10761104
// TODO: we don't know type of each element without phpDoc, it will be mixed
1077-
func (b *blockWalker) checkArrayDimFetchNullSafety(arg ir.Node, fn meta.FuncInfo, paramIndex int, arrayExpr *ir.ArrayDimFetchExpr) {
1105+
func (b *blockWalker) checkArrayDimFetchNullSafety(arg ir.Node, fn meta.FuncInfo, paramIndex int, arrayExpr *ir.ArrayDimFetchExpr, haveVariadic bool) {
10781106
baseVar, ok := arrayExpr.Variable.(*ir.SimpleVar)
10791107
if !ok {
10801108
return
@@ -1091,7 +1119,7 @@ func (b *blockWalker) checkArrayDimFetchNullSafety(arg ir.Node, fn meta.FuncInfo
10911119
}
10921120

10931121
// TODO: we don't know type of each element without phpDoc, it will be mixed
1094-
func (b *blockWalker) checkListExprNullSafety(arg ir.Node, fn meta.FuncInfo, paramIndex int, listExpr *ir.ListExpr) {
1122+
func (b *blockWalker) checkListExprNullSafety(arg ir.Node, fn meta.FuncInfo, paramIndex int, listExpr *ir.ListExpr, haveVariadic bool) {
10951123
for _, item := range listExpr.Items {
10961124
if item == nil {
10971125
continue

src/types/predicates.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ func IsTypeNullable(typ Map) bool {
4747
return isNullable
4848
}
4949

50+
func IsTypeMixed(typ Map) bool {
51+
isMixed := false
52+
typ.Iterate(func(t string) {
53+
if strings.Contains(t, "mixed") {
54+
isMixed = true
55+
}
56+
})
57+
return isMixed
58+
}
59+
5060
func Alias(s string) (string, bool) {
5161
alias, has := aliases[s]
5262
return alias, has

0 commit comments

Comments
 (0)