@@ -1051,7 +1051,7 @@ func (b *blockWalker) checkNullSafetyCallArgsF(args []ir.Node, fn meta.FuncInfo)
1051
1051
b .checkListExprNullSafety (arg , fn , i , a , haveVariadic )
1052
1052
1053
1053
case * ir.PropertyFetchExpr :
1054
- b .checkPropertyFetchNullSafety (a )
1054
+ b .checkPropertyFetchNullSafety (a , fn , i , haveVariadic )
1055
1055
}
1056
1056
}
1057
1057
}
@@ -1138,7 +1138,7 @@ func (b *blockWalker) checkListExprNullSafety(arg ir.Node, fn meta.FuncInfo, par
1138
1138
}
1139
1139
}
1140
1140
1141
- func (b * blockWalker ) checkPropertyFetchNullSafety (expr * ir.PropertyFetchExpr ) {
1141
+ func (b * blockWalker ) checkPropertyFetchNullSafety (expr * ir.PropertyFetchExpr , fn meta. FuncInfo , paramIndex int , haveVariadic bool ) {
1142
1142
objVar , ok := expr .Variable .(* ir.SimpleVar )
1143
1143
1144
1144
if ok {
@@ -1150,19 +1150,40 @@ func (b *blockWalker) checkPropertyFetchNullSafety(expr *ir.PropertyFetchExpr) {
1150
1150
if okPrp {
1151
1151
property := classInfo .Properties [prp .Value ]
1152
1152
1153
- if types .IsTypeNullable (property .Typ ) {
1153
+ isPrpNullable := types .IsTypeNullable (property .Typ )
1154
+ if haveVariadic {
1155
+ // If the parameter is outside the declared parameters, we check the latter as a variable
1156
+ if paramIndex >= len (fn .Params )- 1 {
1157
+ lastParam := fn .Params [len (fn .Params )- 1 ] // last param (variadic ...args)
1158
+ if types .IsTypeMixed (lastParam .Typ ) {
1159
+ return
1160
+ }
1161
+
1162
+ paramAllowsNull := types .IsTypeNullable (lastParam .Typ )
1163
+ if isPrpNullable && ! paramAllowsNull {
1164
+ b .report (expr , LevelError , "notNullSafety" ,
1165
+ "potential null dereference when accessing property '%s'" , prp .Value )
1166
+ }
1167
+ return
1168
+
1169
+ }
1170
+ }
1171
+
1172
+ paramAllowsNull := types .IsTypeNullable (fn .Params [paramIndex ].Typ )
1173
+
1174
+ if isPrpNullable && ! paramAllowsNull {
1154
1175
b .report (expr , LevelError , "notNullSafety" ,
1155
1176
"potential null dereference when accessing property '%s'" , prp .Value )
1156
1177
}
1178
+
1179
+ println (classInfo .Name )
1157
1180
}
1158
1181
1159
- println (classInfo .Name )
1182
+ // TODO: check difficult chains like $a->b->c->d
1183
+ /* if nestedProp, ok := expr.Variable.(*ir.PropertyFetchExpr); ok {
1184
+ b.checkPropertyFetchNullSafety(nestedProp)
1185
+ }*/
1160
1186
}
1161
-
1162
- // TODO: check difficult chains like $a->b->c->d
1163
- /* if nestedProp, ok := expr.Variable.(*ir.PropertyFetchExpr); ok {
1164
- b.checkPropertyFetchNullSafety(nestedProp)
1165
- }*/
1166
1187
}
1167
1188
1168
1189
func (b * blockWalker ) handleCallArgs (args []ir.Node , fn meta.FuncInfo ) {
0 commit comments