From 0b016da203177f93e3d5b52ea66d0824d7e5b662 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 1 Mar 2014 17:40:15 +0100 Subject: Do not mark all calls to erlang:is_record/3 as safe Calls to erlang:is_record/3 where the second and third arguments are not respectively a literal atom and a literal integer can't be transformed to guards and thus are not safe. Reported-by: Ulf Norell --- lib/compiler/src/sys_core_fold.erl | 12 +++++++++--- lib/compiler/test/record_SUITE.erl | 8 ++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index eb9c302334..4ef345f563 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -2346,10 +2346,16 @@ is_safe_bool_expr(Core, Sub) -> is_safe_bool_expr_1(Core, Sub, gb_sets:empty()). is_safe_bool_expr_1(#c_call{module=#c_literal{val=erlang}, - name=#c_literal{val=is_record}, - args=[_,_]}, - _Sub, _BoolVars) -> + name=#c_literal{val=is_record}, + args=[A,#c_literal{val=Tag},#c_literal{val=Size}]}, + Sub, _BoolVars) when is_atom(Tag), is_integer(Size) -> + is_safe_simple(A, Sub); +is_safe_bool_expr_1(#c_call{module=#c_literal{val=erlang}, + name=#c_literal{val=is_record}}, + _Sub, _BoolVars) -> %% The is_record/2 BIF is NOT allowed in guards. + %% The is_record/3 BIF where its second argument is not an atom or its third + %% is not an integer is NOT allowed in guards. %% %% NOTE: Calls like is_record(Expr, LiteralTag), where LiteralTag %% is a literal atom referring to a defined record, have already diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl index c9f5a2053e..f736e14bf6 100644 --- a/lib/compiler/test/record_SUITE.erl +++ b/lib/compiler/test/record_SUITE.erl @@ -369,6 +369,14 @@ record_test_3(Config) when is_list(Config) -> ?line false = is_record(id(#barf{}), id(barf), id(42)), ?line false = is_record(id(#barf{}), id(foo), id(6)), + Rec = id(#barf{}), + Good = id(barf), + Bad = id(foo), + Size = id(6), + + true = is_record(Rec, Good, Size) orelse error, + error = is_record(Rec, Bad, Size) orelse error, + ok. record_access_in_guards(Config) when is_list(Config) -> -- cgit v1.2.3