Try to avoid crashing on invalid key length

May occurr in corrupted files.
This commit is contained in:
martinsumner 2016-11-29 00:27:23 +00:00
parent b62b38caa6
commit dd6201b34b

View file

@ -392,23 +392,32 @@ reader({get_positions, SampleSize}, _From, State) ->
end; end;
reader({direct_fetch, PositionList, Info}, _From, State) -> reader({direct_fetch, PositionList, Info}, _From, State) ->
H = State#state.handle, H = State#state.handle,
case Info of FilterFalseKey = fun(Tpl) -> case element(1, Tpl) of
key_only -> false ->
KeyList = lists:map(fun(P) -> false;
extract_key(H, P) end, _Key ->
PositionList), {true, Tpl}
{reply, KeyList, reader, State}; end end,
key_size -> Reply =
KeySizeList = lists:map(fun(P) -> case Info of
extract_key_size(H, P) end, key_only ->
PositionList), FM = lists:filtermap(
{reply, KeySizeList, reader, State}; fun(P) ->
key_value_check -> FilterFalseKey(extract_key(H, P)) end,
KVCList = lists:map(fun(P) -> PositionList),
extract_key_value_check(H, P) end, lists:map(fun(T) -> element(1, T) end, FM);
PositionList), key_size ->
{reply, KVCList, reader, State} lists:filtermap(
end; fun(P) ->
FilterFalseKey(extract_key_size(H, P)) end,
PositionList);
key_value_check ->
lists:filtermap(
fun(P) ->
FilterFalseKey(extract_key_value_check(H, P)) end,
PositionList)
end,
{reply, Reply, reader, State};
reader(cdb_complete, _From, State) -> reader(cdb_complete, _From, State) ->
ok = file:close(State#state.handle), ok = file:close(State#state.handle),
{stop, normal, {ok, State#state.filename}, State#state{handle=undefined}}; {stop, normal, {ok, State#state.filename}, State#state{handle=undefined}};
@ -493,7 +502,8 @@ handle_sync_event(cdb_firstkey, _From, StateName, State) ->
?BASE_POSITION -> ?BASE_POSITION ->
empty; empty;
_ -> _ ->
extract_key(State#state.handle, ?BASE_POSITION) element(1, extract_key(State#state.handle,
?BASE_POSITION))
end, end,
{reply, FirstKey, StateName, State}; {reply, FirstKey, StateName, State};
handle_sync_event(cdb_filename, _From, StateName, State) -> handle_sync_event(cdb_filename, _From, StateName, State) ->
@ -893,17 +903,17 @@ extract_kvpair(Handle, [Position|Rest], Key) ->
extract_key(Handle, Position) -> extract_key(Handle, Position) ->
{ok, _} = file:position(Handle, Position), {ok, _} = file:position(Handle, Position),
{KeyLength, _ValueLength} = read_next_2_integers(Handle), {KeyLength, _ValueLength} = read_next_2_integers(Handle),
read_next_term(Handle, KeyLength). {safe_read_next_term(Handle, KeyLength)}.
extract_key_size(Handle, Position) -> extract_key_size(Handle, Position) ->
{ok, _} = file:position(Handle, Position), {ok, _} = file:position(Handle, Position),
{KeyLength, ValueLength} = read_next_2_integers(Handle), {KeyLength, ValueLength} = read_next_2_integers(Handle),
{read_next_term(Handle, KeyLength), ValueLength}. {safe_read_next_term(Handle, KeyLength), ValueLength}.
extract_key_value_check(Handle, Position) -> extract_key_value_check(Handle, Position) ->
{ok, _} = file:position(Handle, Position), {ok, _} = file:position(Handle, Position),
{KeyLength, ValueLength} = read_next_2_integers(Handle), {KeyLength, ValueLength} = read_next_2_integers(Handle),
K = read_next_term(Handle, KeyLength), K = safe_read_next_term(Handle, KeyLength),
{Check, V} = read_next_term(Handle, ValueLength, crc), {Check, V} = read_next_term(Handle, ValueLength, crc),
{K, V, Check}. {K, V, Check}.
@ -1676,21 +1686,20 @@ get_keys_byposition_simple_test() ->
io:format("Position list of ~w~n", [PositionList]), io:format("Position list of ~w~n", [PositionList]),
?assertMatch(3, length(PositionList)), ?assertMatch(3, length(PositionList)),
R1 = cdb_directfetch(P2, PositionList, key_only), R1 = cdb_directfetch(P2, PositionList, key_only),
io:format("R1 ~w~n", [R1]),
?assertMatch(3, length(R1)), ?assertMatch(3, length(R1)),
lists:foreach(fun(Key) -> lists:foreach(fun(Key) ->
Check = lists:member(Key, KeyList), ?assertMatch(true, lists:member(Key, KeyList)) end,
?assertMatch(Check, true) end,
R1), R1),
R2 = cdb_directfetch(P2, PositionList, key_size), R2 = cdb_directfetch(P2, PositionList, key_size),
?assertMatch(3, length(R2)), ?assertMatch(3, length(R2)),
lists:foreach(fun({Key, _Size}) -> lists:foreach(fun({Key, _Size}) ->
Check = lists:member(Key, KeyList), ?assertMatch(true, lists:member(Key, KeyList)) end,
?assertMatch(Check, true) end,
R2), R2),
R3 = cdb_directfetch(P2, PositionList, key_value_check), R3 = cdb_directfetch(P2, PositionList, key_value_check),
?assertMatch(3, length(R3)), ?assertMatch(3, length(R3)),
lists:foreach(fun({Key, Value, Check}) -> lists:foreach(fun({Key, Value, Check}) ->
?assertMatch(Check, true), ?assertMatch(true, Check),
{K, V} = cdb_get(P2, Key), {K, V} = cdb_get(P2, Key),
?assertMatch(K, Key), ?assertMatch(K, Key),
?assertMatch(V, Value) end, ?assertMatch(V, Value) end,