aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStavros Aronis <[email protected]>2011-03-21 18:37:32 +0200
committerHenrik Nord <[email protected]>2011-05-04 15:06:16 +0200
commitc69947da87a5f8b1f1ec6020b2623ce4614c5217 (patch)
treed46de27f07c79131b06ad5e0ce6d79c9854a6bd0
parent7afd92015a0d1c32d5fb9f8a58d1fd4326aaa522 (diff)
downloadotp-c69947da87a5f8b1f1ec6020b2623ce4614c5217.tar.gz
otp-c69947da87a5f8b1f1ec6020b2623ce4614c5217.tar.bz2
otp-c69947da87a5f8b1f1ec6020b2623ce4614c5217.zip
Add small/tuple_set_crash
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash15
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/tuple_set_crash.erl207
2 files changed, 222 insertions, 0 deletions
diff --git a/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash b/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash
new file mode 100644
index 0000000000..191d3d4173
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash
@@ -0,0 +1,15 @@
+
+tuple_set_crash.erl:103: Invalid type specification for function tuple_set_crash:parse_device_properties/1. The success typing is (<<_:48>>) -> [{'controller_description',binary()} | {'controller_name',binary()} | {'controller_status',byte()} | {'fw_version',<<_:24>>}]
+tuple_set_crash.erl:123: Invalid type specification for function tuple_set_crash:parse_video_target_info/1. The success typing is (<<_:48>>) -> [{'status',byte()} | {'target_id',non_neg_integer()},...]
+tuple_set_crash.erl:127: Invalid type specification for function tuple_set_crash:parse_audio_target_info/1. The success typing is (<<_:48>>) -> [{'master_volume',char()} | {'status',byte()} | {'target_id',non_neg_integer()},...]
+tuple_set_crash.erl:138: Invalid type specification for function tuple_set_crash:parse_av_device_info/1. The success typing is (<<_:48>>) -> [{'address',byte()} | {'device_id',non_neg_integer()} | {'model',binary()} | {'status',byte()},...]
+tuple_set_crash.erl:143: The pattern <<TargetId:32/integer-little-unit:1,Rest1/binary-unit:8>> can never match the type <<_:8>>
+tuple_set_crash.erl:155: Invalid type specification for function tuple_set_crash:parse_video_output_info/1. The success typing is (<<_:48>>) -> [{'audio_volume',char()} | {'display_type',binary()} | {'output_id',non_neg_integer()},...]
+tuple_set_crash.erl:160: The pattern <<DeviceId:32/integer-little-unit:1,Rest1/binary-unit:8>> can never match the type <<_:8>>
+tuple_set_crash.erl:171: Invalid type specification for function tuple_set_crash:parse_audio_output_info/1. The success typing is (<<_:48>>) -> [{'output_id',non_neg_integer()},...]
+tuple_set_crash.erl:176: The pattern <<DeviceId:32/integer-little-unit:1,Rest1/binary-unit:8>> can never match the type <<_:8>>
+tuple_set_crash.erl:179: The pattern <<AudioVolume:16/integer-little-unit:1,Rest2/binary-unit:8>> can never match the type <<_:8>>
+tuple_set_crash.erl:182: The pattern <<Delay:16/integer-little-unit:1,_Padding/binary-unit:8>> can never match the type <<_:8>>
+tuple_set_crash.erl:62: The pattern {'play_list', _Playlist} can never match the type 'ok' | {'device_properties',[{atom(),_}]} | {'error',[{atom(),_}]}
+tuple_set_crash.erl:64: The pattern {'error', 17} can never match the type 'ok' | {'device_properties',[{atom(),_}]} | {'error',[{atom(),_}]}
+tuple_set_crash.erl:83: The specification for tuple_set_crash:parse_message/1 states that the function might also return {'media_item_url_reply',integer(),binary()} but the inferred return is 'ok' | {'audio_device_info' | 'audio_output_info' | 'audio_target_info' | 'device_properties' | 'error' | 'video_device_info' | 'video_output_info' | 'video_target_info',[{'address' | 'audio_volume' | 'controller_description' | 'controller_name' | 'controller_status' | 'device_id' | 'display_type' | 'fw_version' | 'master_volume' | 'model' | 'output_id' | 'status' | 'target_id',binary() | non_neg_integer()}] | 1..255}
diff --git a/lib/dialyzer/test/small_SUITE_data/src/tuple_set_crash.erl b/lib/dialyzer/test/small_SUITE_data/src/tuple_set_crash.erl
new file mode 100644
index 0000000000..5503f39412
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/tuple_set_crash.erl
@@ -0,0 +1,207 @@
+%% ====================================================================
+%% Program which resulted in an erl_types crash due to incomplete
+%% handling of tuple_sets in function inf_tuples_in_sets/4.
+%% Reported by Alexey Romanov on 10/10/2010 and fixed 16/10/2010.
+%% Stavros Aronis provided a better fix of the issue on 8/11/2010.
+%% ====================================================================
+
+-module(tuple_set_crash).
+-export([test/5]).
+
+%% ====================================================================
+
+-define(PREPEND_IF_BIT_SET(BitMap, Bit,
+ PatternInBinary, PatternInList,
+ OldRestVar, NewRestVar,
+ OldAccVar, NewAccVar),
+ case byteset:contains(Bit, BitMap) of
+ true ->
+ <<PatternInBinary, NewRestVar/binary>> = OldRestVar,
+ NewAccVar = [PatternInList | OldAccVar];
+ false ->
+ NewRestVar = OldRestVar,
+ NewAccVar = OldAccVar
+ end).
+
+%% ====================================================================
+
+%% Types used in parsing binaries
+-define(BITMAP1, 8/integer-big-unsigned).
+-define(BYTE, 8/integer-little-unsigned).
+-define(WORD, 16/integer-little-unsigned).
+-define(DWORD, 32/integer-little-unsigned).
+-define(DATE, 16/integer-little-signed).
+-define(TIME, 32/float-little-unsigned).
+-define(TINY_STRING_M(Var, Size), Size:?BYTE, Var:Size/binary).
+-define(SMALL_STRING_M(Var, Size), Size:?WORD, Var:Size/binary).
+
+-type config_change() ::
+ {device_properties |
+ video_target |
+ audio_target |
+ video_device |
+ audio_device |
+ video_output |
+ audio_output, [{atom(), any()}]}.
+
+-type message_from_server() ::
+ ok |
+ {error, atom()} |
+ config_change() |
+ {media_item_url_reply, integer(), binary()}.
+
+%% ====================================================================
+
+-spec test(integer(), [integer()], binary(), binary(), binary()) -> {binary(), binary()}.
+test(_TargetId, [], _Key, IVT, IVF) ->
+ {IVT, IVF};
+test(TargetId, [Date | DateTail], Key, IVT, IVF) ->
+ PlayListRequest = play_list_request(TargetId, Date),
+ {ok, Reply, IVT1, IVF1} = culprit(PlayListRequest, Key, IVT, IVF),
+ case Reply of
+ {play_list, _Playlist} ->
+ test(TargetId, DateTail, Key, IVT1, IVF1);
+ {error, 16#11} ->
+ {IVT1, IVF1} %% we can finish early
+ end.
+
+-spec culprit(binary(), binary(), binary(), binary()) ->
+ {ok, message_from_server(), binary(), binary()}.
+culprit(Message, Key, IVecToServer, IVecFromServer) ->
+ {Packet, NewIVecToServer} = message_to_packet(Message, Key, IVecToServer),
+ Message = crypto:aes_cbc_128_decrypt(Key, IVecFromServer, Packet),
+ NewIVecFromServer = crypto:aes_cbc_ivec(Packet),
+ ParsedMessage = parse_message(Message),
+ {ok, ParsedMessage, NewIVecToServer, NewIVecFromServer}.
+
+%% ====================================================================
+
+-spec play_list_request(integer(), integer()) -> binary().
+play_list_request(TargetId, Date) ->
+ <<16#06:?WORD, TargetId:?DWORD, Date:?DATE>>.
+
+-spec parse_message(binary()) -> message_from_server().
+parse_message(<<MessageID:?WORD, Rest/binary>>) ->
+ case MessageID of
+ 16#00 -> parse_error_code(Rest);
+ 16#22 -> {device_properties, parse_device_properties(Rest)};
+ 16#24 -> {video_target_info, parse_video_target_info(Rest)};
+ 16#25 -> {audio_target_info, parse_audio_target_info(Rest)};
+ 16#26 -> {video_device_info, parse_av_device_info(Rest)};
+ 16#27 -> {audio_device_info, parse_av_device_info(Rest)};
+ 16#28 -> {video_output_info, parse_video_output_info(Rest)};
+ 16#29 -> {audio_output_info, parse_audio_output_info(Rest)}
+ end.
+
+-spec parse_error_code(binary()) -> ok | {error, integer()}.
+parse_error_code(<<ErrorCode:?BYTE, _Padding/binary>>) ->
+ case ErrorCode of
+ 0 -> ok;
+ _ -> {error, ErrorCode}
+ end.
+
+-spec parse_device_properties(binary()) -> config_change().
+parse_device_properties(<<BitMap:?BITMAP1, Rest/binary>>) ->
+ Acc0 = [],
+ ?PREPEND_IF_BIT_SET(BitMap, 0,
+ FwVersion:3/binary, {fw_version, FwVersion},
+ Rest, Rest1, Acc0, Acc1),
+ ?PREPEND_IF_BIT_SET(BitMap, 1,
+ ?TINY_STRING_M(ControllerName, _S1),
+ {controller_name, ControllerName},
+ Rest1, Rest2, Acc1, Acc2),
+ ?PREPEND_IF_BIT_SET(BitMap, 2,
+ ?SMALL_STRING_M(ControllerDescription, _S2),
+ {controller_description, ControllerDescription},
+ Rest2, Rest3, Acc2, Acc3),
+ ?PREPEND_IF_BIT_SET(BitMap, 3,
+ ControllerStatus:?BYTE,
+ {controller_status, ControllerStatus},
+ Rest3, _Padding, Acc3, Acc4),
+ Acc4.
+
+-spec parse_video_target_info(binary()) -> config_change().
+parse_video_target_info(<<TargetId:?DWORD, Status:?BYTE, _Padding/binary>>) ->
+ [{target_id, TargetId}, {status, Status}].
+
+-spec parse_audio_target_info(binary()) -> [config_change()].
+parse_audio_target_info(<<TargetId:?DWORD, BitMap:?BITMAP1, Rest/binary>>) ->
+ Acc0 = [{target_id, TargetId}],
+ ?PREPEND_IF_BIT_SET(BitMap, 0,
+ Status:?BYTE, {status, Status},
+ Rest, Rest1, Acc0, Acc1),
+ ?PREPEND_IF_BIT_SET(BitMap, 1,
+ MasterVolume:?WORD, {master_volume, MasterVolume},
+ Rest1, _Padding, Acc1, Acc2),
+ Acc2.
+
+-spec parse_av_device_info(binary()) -> [config_change()].
+parse_av_device_info(<<DeviceId:?DWORD, BitMap:?BITMAP1, Rest/binary>>) ->
+ Acc0 = [{device_id, DeviceId}],
+ ?PREPEND_IF_BIT_SET(BitMap, 0,
+ TargetId:?DWORD, {target_id, TargetId},
+ Rest, Rest1, Acc0, Acc1),
+ ?PREPEND_IF_BIT_SET(BitMap, 1,
+ ?TINY_STRING_M(Model, _S1), {model, Model},
+ Rest1, Rest2, Acc1, Acc2),
+ ?PREPEND_IF_BIT_SET(BitMap, 2,
+ Address:?BYTE, {address, Address},
+ Rest2, Rest3, Acc2, Acc3),
+ ?PREPEND_IF_BIT_SET(BitMap, 3,
+ Status:?BYTE, {status, Status},
+ Rest3, _Padding, Acc3, Acc4),
+ Acc4.
+
+-spec parse_video_output_info(binary()) -> [config_change()].
+parse_video_output_info(<<Output:?DWORD, BitMap:?BITMAP1, Rest/binary>>) ->
+ Acc0 = [{output_id, Output}],
+ ?PREPEND_IF_BIT_SET(BitMap, 0,
+ DeviceId:?DWORD, {device_id, DeviceId},
+ Rest, Rest1, Acc0, Acc1),
+ ?PREPEND_IF_BIT_SET(BitMap, 1,
+ ?TINY_STRING_M(DisplayType, _S1),
+ {display_type, DisplayType},
+ Rest1, Rest2, Acc1, Acc2),
+ ?PREPEND_IF_BIT_SET(BitMap, 2,
+ AudioVolume:?WORD,
+ {audio_volume, AudioVolume},
+ Rest2, _Padding, Acc2, Acc3),
+ Acc3.
+
+-spec parse_audio_output_info(binary()) -> [config_change()].
+parse_audio_output_info(<<Output:?DWORD, BitMap:?BITMAP1, Rest/binary>>) ->
+ Acc0 = [{output_id, Output}],
+ ?PREPEND_IF_BIT_SET(BitMap, 0,
+ DeviceId:?DWORD, {device_id, DeviceId},
+ Rest, Rest1, Acc0, Acc1),
+ ?PREPEND_IF_BIT_SET(BitMap, 1,
+ AudioVolume:?WORD, {audio_volume, AudioVolume},
+ Rest1, Rest2, Acc1, Acc2),
+ ?PREPEND_IF_BIT_SET(BitMap, 2,
+ Delay:?WORD, {delay, Delay},
+ Rest2, _Padding, Acc2, Acc3),
+ Acc3.
+
+-spec message_to_packet(binary(), binary(), binary()) -> {binary(), binary()}.
+message_to_packet(Message, Key, IVec) ->
+ PaddedMessage = pad_pkcs5(Message),
+ Packet = crypto:aes_cbc_128_encrypt(Key, IVec, PaddedMessage),
+ TotalSize = byte_size(Packet),
+ NewIVec = crypto:aes_cbc_ivec(Packet),
+ {<<TotalSize:?WORD, Packet/binary>>, NewIVec}.
+
+-spec pad_pkcs5(binary()) -> binary().
+pad_pkcs5(Message) ->
+ Size = byte_size(Message),
+ PaddingSize = case Size rem 16 of
+ 0 -> 0;
+ Rem -> 16 - Rem
+ end,
+ pad_pkcs5(Message, PaddingSize, PaddingSize).
+
+-spec pad_pkcs5(binary(), integer(), integer()) -> binary().
+pad_pkcs5(Message, _PaddingSize, 0) ->
+ Message;
+pad_pkcs5(Message, PaddingSize, PaddingSizeRemaining) ->
+ pad_pkcs5(<<Message/binary, PaddingSize:?BYTE>>,
+ PaddingSize, PaddingSizeRemaining - 1).