fix(rule_engine): support non-byte sized input to bin2hexstr

The rule engine subbits function can return a bitstring which size is
not divisible by 8. Therefore, it makes sense that the rule engine
function bin2hexstr can handle such bitstrings as well. This is fixed by
this commit.

Fixes:
https://github.com/emqx/emqx/issues/12586
https://emqx.atlassian.net/browse/EMQX-11943
This commit is contained in:
Kjell Winblad 2024-03-05 16:55:43 +01:00
parent 78d5f76f70
commit 69114bc6c2
2 changed files with 32 additions and 1 deletions

View File

@ -707,7 +707,20 @@ map(Data) ->
error(badarg, [Data]). error(badarg, [Data]).
bin2hexstr(Bin) when is_binary(Bin) -> bin2hexstr(Bin) when is_binary(Bin) ->
emqx_utils:bin_to_hexstr(Bin, upper). emqx_utils:bin_to_hexstr(Bin, upper);
%% If Bin is a bitstring which is not divisible by 8, we pad it and then do the
%% conversion
bin2hexstr(Bin) when is_bitstring(Bin), (8 - (bit_size(Bin) rem 8)) >= 4 ->
PadSize = 8 - (bit_size(Bin) rem 8),
Padding = <<0:PadSize>>,
BinToConvert = <<Padding/bitstring, Bin/bitstring>>,
<<_FirstByte:8, HexStr/binary>> = emqx_utils:bin_to_hexstr(BinToConvert, upper),
HexStr;
bin2hexstr(Bin) when is_bitstring(Bin) ->
PadSize = 8 - (bit_size(Bin) rem 8),
Padding = <<0:PadSize>>,
BinToConvert = <<Padding/bitstring, Bin/bitstring>>,
emqx_utils:bin_to_hexstr(BinToConvert, upper).
hexstr2bin(Str) when is_binary(Str) -> hexstr2bin(Str) when is_binary(Str) ->
emqx_utils:hexstr_to_bin(Str). emqx_utils:hexstr_to_bin(Str).

View File

@ -198,6 +198,19 @@ t_bin2hexstr(_) ->
?assertEqual(<<"0102">>, emqx_rule_funcs:bin2hexstr(<<1, 2>>)), ?assertEqual(<<"0102">>, emqx_rule_funcs:bin2hexstr(<<1, 2>>)),
?assertEqual(<<"1121">>, emqx_rule_funcs:bin2hexstr(<<17, 33>>)). ?assertEqual(<<"1121">>, emqx_rule_funcs:bin2hexstr(<<17, 33>>)).
t_bin2hexstr_not_even_bytes(_) ->
?assertEqual(<<"0102">>, emqx_rule_funcs:bin2hexstr(<<1:5, 2>>)),
?assertEqual(<<"1002">>, emqx_rule_funcs:bin2hexstr(<<16:5, 2>>)),
?assertEqual(<<"1002">>, emqx_rule_funcs:bin2hexstr(<<16:8, 2>>)),
?assertEqual(<<"102">>, emqx_rule_funcs:bin2hexstr(<<1:4, 2>>)),
?assertEqual(<<"102">>, emqx_rule_funcs:bin2hexstr(<<1:3, 2>>)),
?assertEqual(<<"102">>, emqx_rule_funcs:bin2hexstr(<<1:1, 2>>)),
?assertEqual(<<"002">>, emqx_rule_funcs:bin2hexstr(<<2:1, 2>>)),
?assertEqual(<<"02">>, emqx_rule_funcs:bin2hexstr(<<2>>)),
?assertEqual(<<"2">>, emqx_rule_funcs:bin2hexstr(<<2:2>>)),
?assertEqual(<<"1121">>, emqx_rule_funcs:bin2hexstr(<<17, 33>>)),
?assertEqual(<<"01121">>, emqx_rule_funcs:bin2hexstr(<<17:9, 33>>)).
t_hex_convert(_) -> t_hex_convert(_) ->
?PROPTEST(hex_convert). ?PROPTEST(hex_convert).
@ -922,6 +935,11 @@ t_subbits_5_args(_) ->
apply_func(subbits, [<<456:32/integer>>, 1, 32, <<"integer">>, <<"unsigned">>]) apply_func(subbits, [<<456:32/integer>>, 1, 32, <<"integer">>, <<"unsigned">>])
). ).
t_subbits_not_even_bytes(_) ->
InputBin = apply_func(hexstr2bin, [<<"9F4E58">>]),
SubbitsRes = apply_func(subbits, [InputBin, 1, 6, <<"bits">>, <<"unsigned">>, <<"big">>]),
?assertEqual(<<"27">>, apply_func(bin2hexstr, [SubbitsRes])).
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------
%% Test cases for Hash funcs %% Test cases for Hash funcs
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------