From 69114bc6c20ee72877fb96806b784ab965abd91d Mon Sep 17 00:00:00 2001 From: Kjell Winblad Date: Tue, 5 Mar 2024 16:55:43 +0100 Subject: [PATCH 1/2] 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 --- apps/emqx_rule_engine/src/emqx_rule_funcs.erl | 15 ++++++++++++++- .../test/emqx_rule_funcs_SUITE.erl | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/apps/emqx_rule_engine/src/emqx_rule_funcs.erl b/apps/emqx_rule_engine/src/emqx_rule_funcs.erl index 735025e2b..3cebdd67a 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_funcs.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_funcs.erl @@ -707,7 +707,20 @@ map(Data) -> error(badarg, [Data]). 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 = <>, + <<_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 = <>, + emqx_utils:bin_to_hexstr(BinToConvert, upper). hexstr2bin(Str) when is_binary(Str) -> emqx_utils:hexstr_to_bin(Str). diff --git a/apps/emqx_rule_engine/test/emqx_rule_funcs_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_funcs_SUITE.erl index 3bdfaa5b4..62c31cc2f 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_funcs_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_funcs_SUITE.erl @@ -198,6 +198,19 @@ t_bin2hexstr(_) -> ?assertEqual(<<"0102">>, emqx_rule_funcs:bin2hexstr(<<1, 2>>)), ?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(_) -> ?PROPTEST(hex_convert). @@ -922,6 +935,11 @@ t_subbits_5_args(_) -> 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 %%------------------------------------------------------------------------------ From cd3ecc4ad5151f1a50b73df5c448e7b596210653 Mon Sep 17 00:00:00 2001 From: Kjell Winblad Date: Tue, 5 Mar 2024 17:12:27 +0100 Subject: [PATCH 2/2] docs: add change log entry --- changes/ce/fix-12653.en.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changes/ce/fix-12653.en.md diff --git a/changes/ce/fix-12653.en.md b/changes/ce/fix-12653.en.md new file mode 100644 index 000000000..ce85ae826 --- /dev/null +++ b/changes/ce/fix-12653.en.md @@ -0,0 +1 @@ +The rule engine function `bin2hexstr` now supports bitstring inputs with a bit size that is not divisible by 8. Such bitstrings can be returned by the rule engine function `subbits`.