Packages

Pure Gleam implementation of the Apache Thrift Compact Protocol

Current section

Files

Jump to
thrifty src thrifty@fuzz_utils.erl
Raw

src/thrifty@fuzz_utils.erl

-module(thrifty@fuzz_utils).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/thrifty/fuzz_utils.gleam").
-export([mutate_byte/3, mutate_bit_flip/3, mutate_insert_byte/3, mutate_delete_byte/2, mutate_multi_byte/4]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/thrifty/fuzz_utils.gleam", 28).
?DOC(
" Replace the byte at position `pos` with the provided `value`.\n"
"\n"
" Inputs\n"
" - `data`: the source `BitArray` to mutate.\n"
" - `pos`: zero-based byte index to replace.\n"
" - `value`: integer 0..255 to write at `pos`.\n"
"\n"
" Outputs\n"
" - Returns a new `BitArray` with the replaced byte when `pos` is in range.\n"
" - Returns the original `data` unchanged if `pos` is out of range or on\n"
" unexpected slicing errors.\n"
).
-spec mutate_byte(bitstring(), integer(), integer()) -> bitstring().
mutate_byte(Data, Pos, Value) ->
Size = erlang:byte_size(Data),
case (Pos < 0) orelse (Pos >= Size) of
true ->
Data;
false ->
case gleam_stdlib:bit_array_slice(Data, 0, Pos) of
{error, _} ->
Data;
{ok, Prefix} ->
Suffix_len = (Size - Pos) - 1,
case gleam_stdlib:bit_array_slice(Data, Pos + 1, Suffix_len) of
{error, _} ->
gleam_stdlib:bit_array_concat(
[Prefix, <<Value:8/integer>>]
);
{ok, Suffix} ->
gleam_stdlib:bit_array_concat(
[Prefix, <<Value:8/integer>>, Suffix]
)
end
end
end.
-file("src/thrifty/fuzz_utils.gleam", 155).
-spec pow2(integer()) -> integer().
pow2(Exp) ->
case Exp =< 0 of
true ->
1;
false ->
2 * pow2(Exp - 1)
end.
-file("src/thrifty/fuzz_utils.gleam", 56).
?DOC(
" Flip a single bit in the byte at `pos`.\n"
"\n"
" Inputs\n"
" - `data`: source `BitArray`.\n"
" - `pos`: byte index to modify.\n"
" - `bit_index`: 0..7 bit to flip (0 is LSB).\n"
"\n"
" Outputs\n"
" - `BitArray` with the selected bit flipped, or original data if out of range.\n"
).
-spec mutate_bit_flip(bitstring(), integer(), integer()) -> bitstring().
mutate_bit_flip(Data, Pos, Bit_index) ->
Size = erlang:byte_size(Data),
case (((Pos < 0) orelse (Pos >= Size)) orelse (Bit_index < 0)) orelse (Bit_index
> 7) of
true ->
Data;
false ->
case gleam_stdlib:bit_array_slice(Data, Pos, 1) of
{error, _} ->
Data;
{ok, Bits} ->
case Bits of
<<B:8/integer>> ->
Mask = pow2(Bit_index),
Div = case Mask of
0 -> 0;
Gleam@denominator -> B div Gleam@denominator
end,
Has_bit = (Div rem 2) =:= 1,
New_byte = case Has_bit of
true ->
B - Mask;
false ->
B + Mask
end,
mutate_byte(Data, Pos, New_byte);
_ ->
Data
end
end
end.
-file("src/thrifty/fuzz_utils.gleam", 82).
?DOC(" Insert a single byte at position `pos` shifting the remainder to the right.\n").
-spec mutate_insert_byte(bitstring(), integer(), integer()) -> bitstring().
mutate_insert_byte(Data, Pos, Value) ->
Size = erlang:byte_size(Data),
case (Pos < 0) orelse (Pos > Size) of
true ->
Data;
false ->
case gleam_stdlib:bit_array_slice(Data, 0, Pos) of
{error, _} ->
Data;
{ok, Prefix} ->
case gleam_stdlib:bit_array_slice(Data, Pos, Size - Pos) of
{error, _} ->
gleam_stdlib:bit_array_concat(
[Prefix, <<Value:8/integer>>]
);
{ok, Suffix} ->
gleam_stdlib:bit_array_concat(
[Prefix, <<Value:8/integer>>, Suffix]
)
end
end
end.
-file("src/thrifty/fuzz_utils.gleam", 100).
?DOC(" Delete a single byte at position `pos`.\n").
-spec mutate_delete_byte(bitstring(), integer()) -> bitstring().
mutate_delete_byte(Data, Pos) ->
Size = erlang:byte_size(Data),
case (Pos < 0) orelse (Pos >= Size) of
true ->
Data;
false ->
case gleam_stdlib:bit_array_slice(Data, 0, Pos) of
{error, _} ->
Data;
{ok, Prefix} ->
case gleam_stdlib:bit_array_slice(
Data,
Pos + 1,
(Size - Pos) - 1
) of
{error, _} ->
Prefix;
{ok, Suffix} ->
gleam_stdlib:bit_array_concat([Prefix, Suffix])
end
end
end.
-file("src/thrifty/fuzz_utils.gleam", 145).
-spec gen_bytes(integer(), integer()) -> bitstring().
gen_bytes(Count, Value) ->
case Count =< 0 of
true ->
<<>>;
false ->
Tail = gen_bytes(Count - 1, Value),
<<Value:8/integer, Tail/bitstring>>
end.
-file("src/thrifty/fuzz_utils.gleam", 117).
?DOC(" Overwrite `len` bytes starting at `pos` with repeated `value` bytes.\n").
-spec mutate_multi_byte(bitstring(), integer(), integer(), integer()) -> bitstring().
mutate_multi_byte(Data, Pos, Len, Value) ->
Size = erlang:byte_size(Data),
case ((Pos < 0) orelse (Pos >= Size)) orelse (Len =< 0) of
true ->
Data;
false ->
Write_len = case (Pos + Len) > Size of
true ->
Size - Pos;
false ->
Len
end,
case gleam_stdlib:bit_array_slice(Data, 0, Pos) of
{error, _} ->
Data;
{ok, Prefix} ->
Repeated = gen_bytes(Write_len, Value),
case gleam_stdlib:bit_array_slice(
Data,
Pos + Write_len,
(Size - Pos) - Write_len
) of
{error, _} ->
gleam_stdlib:bit_array_concat([Prefix, Repeated]);
{ok, Suffix} ->
gleam_stdlib:bit_array_concat(
[Prefix, Repeated, Suffix]
)
end
end
end.