Prechádzať zdrojové kódy

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
Kjell Winblad 2 rokov pred
rodič
commit
69114bc6c2

+ 14 - 1
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 = <<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) ->
     emqx_utils:hexstr_to_bin(Str).

+ 18 - 0
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
 %%------------------------------------------------------------------------------