From 69f44a163a91f75d90acc6090f97fefbc47ca037 Mon Sep 17 00:00:00 2001 From: lucioleKi Date: Wed, 19 Feb 2025 15:21:00 +0100 Subject: [PATCH] stdlib: Fix linter crash from invalid zip generators Fix https://github.com/erlang/otp/issues/9461 An invalid generator in a zip generator is excluded from the analysis for individual generators. If there is no valid generator in a zip generator, no analysis for generator is applied. --- lib/stdlib/src/erl_lint.erl | 42 ++++++++++++++++++++---------- lib/stdlib/test/erl_lint_SUITE.erl | 17 +++++++++++- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index a4bbbf5b5353..4426b0baefeb 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -4071,10 +4071,16 @@ lc_quals(Qs, Vt0, St0) -> {Vt,Uvt,St} = lc_quals(Qs, Vt0, [], St0#lint{recdef_top = false}), {Vt,Uvt,St#lint{recdef_top = OldRecDef}}. -lc_quals([{zip,_Anno,Gens} | Qs], Vt0, Uvt0, St0) -> - St1 = are_all_generators(Gens,St0), - {Vt,Uvt,St} = handle_generators(Gens,Vt0,Uvt0,St1), - lc_quals(Qs, Vt, Uvt, St); +lc_quals([{zip,_Anno,Gens0} | Qs], Vt0, Uvt0, St0) -> + {Gens1, St1} = filter_generators(Gens0, [], St0), + {Vt,Uvt,St2} = case Gens1 of + [] -> + %% No valid generators. + {Vt0, Uvt0, St1}; + _ -> + handle_generators(Gens1, Vt0, Uvt0, St1) + end, + lc_quals(Qs, Vt, Uvt, St2); lc_quals([{generate,_Anno,P,E} | Qs], Vt0, Uvt0, St0) -> {Vt,Uvt,St} = handle_generator(P,E,Vt0,Uvt0,St0), lc_quals(Qs, Vt, Uvt, St); @@ -4111,16 +4117,24 @@ is_guard_test2_info(#lint{records=RDs,locals=Locals,imports=Imports}) -> is_imported_function(Imports, FA) end}. -are_all_generators([{generate,_,_,_}|Qs],St) -> are_all_generators(Qs,St); -are_all_generators([{generate_strict,_,_,_}|Qs],St) -> are_all_generators(Qs,St); -are_all_generators([{b_generate,_,_,_}|Qs],St) -> are_all_generators(Qs,St); -are_all_generators([{b_generate_strict,_,_,_}|Qs],St) -> are_all_generators(Qs,St); -are_all_generators([{m_generate,_,_,_}|Qs],St) -> are_all_generators(Qs,St); -are_all_generators([{m_generate_strict,_,_,_}|Qs],St) -> are_all_generators(Qs,St); -are_all_generators([Q|_Qs],St) -> - Anno1 = element(2,Q), - add_error(Anno1, illegal_zip_generator, St); -are_all_generators([],St) -> St. +filter_generators([{generate,_,_,_}=Q|Qs], Acc, St) -> + filter_generators(Qs, [Q|Acc], St); +filter_generators([{generate_strict,_,_,_}=Q|Qs], Acc, St) -> + filter_generators(Qs, [Q|Acc], St); +filter_generators([{b_generate,_,_,_}=Q|Qs], Acc, St) -> + filter_generators(Qs, [Q|Acc], St); +filter_generators([{b_generate_strict,_,_,_}=Q|Qs], Acc, St) -> + filter_generators(Qs, [Q|Acc], St); +filter_generators([{m_generate,_,_,_}=Q|Qs], Acc, St) -> + filter_generators(Qs, [Q|Acc], St); +filter_generators([{m_generate_strict,_,_,_}=Q|Qs], Acc, St) -> + filter_generators(Qs, [Q|Acc], St); +filter_generators([Q|Qs], Acc, St0) -> + Anno1 = element(2, Q), + St1 = add_error(Anno1, illegal_zip_generator, St0), + filter_generators(Qs, Acc, St1); +filter_generators([], Acc, St) -> + {reverse(Acc), St}. handle_generators(Gens,Vt,Uvt,St0) -> Ps = [P || {_,_,P,_} <- Gens], diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index f1f789ce4f6f..2f8ab31786cb 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -5632,7 +5632,22 @@ illegal_zip_generator(Config) -> bar() -> [X + Y || X <- [[1,2],[3,4]] && lists:sum(X) > 0 && Y <- [5,6,7]]. ">>, {[]}, - {errors,[{{2,67},erl_lint,illegal_zip_generator}],[]}} + {errors,[{{2,67},erl_lint,illegal_zip_generator}],[]}}, + {not_generator, + <<"-compile({nowarn_unused_function,[{foo,0}]}). + foo() -> [X || X <- [a, b] && F()]. + ">>, + {[]}, + {errors,[{{2,43},erl_lint,illegal_zip_generator}],[]}}, + {not_generator, + <<"-compile({nowarn_unused_function,[{foo,0}]}). + foo() -> [X || a && b]. + ">>, + {[]}, + {errors,[{{2,23},erl_lint,{unbound_var,'X'}}, + {{2,28},erl_lint,illegal_zip_generator}, + {{2,33},erl_lint,illegal_zip_generator}], + []}} ], [] = run(Config,Ts),