Try to avoid crashing on invalid key length
May occurr in corrupted files.
This commit is contained in:
parent
b62b38caa6
commit
dd6201b34b
1 changed files with 35 additions and 26 deletions
|
@ -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,
|
||||||
|
FilterFalseKey = fun(Tpl) -> case element(1, Tpl) of
|
||||||
|
false ->
|
||||||
|
false;
|
||||||
|
_Key ->
|
||||||
|
{true, Tpl}
|
||||||
|
end end,
|
||||||
|
Reply =
|
||||||
case Info of
|
case Info of
|
||||||
key_only ->
|
key_only ->
|
||||||
KeyList = lists:map(fun(P) ->
|
FM = lists:filtermap(
|
||||||
extract_key(H, P) end,
|
fun(P) ->
|
||||||
|
FilterFalseKey(extract_key(H, P)) end,
|
||||||
PositionList),
|
PositionList),
|
||||||
{reply, KeyList, reader, State};
|
lists:map(fun(T) -> element(1, T) end, FM);
|
||||||
key_size ->
|
key_size ->
|
||||||
KeySizeList = lists:map(fun(P) ->
|
lists:filtermap(
|
||||||
extract_key_size(H, P) end,
|
fun(P) ->
|
||||||
PositionList),
|
FilterFalseKey(extract_key_size(H, P)) end,
|
||||||
{reply, KeySizeList, reader, State};
|
PositionList);
|
||||||
key_value_check ->
|
key_value_check ->
|
||||||
KVCList = lists:map(fun(P) ->
|
lists:filtermap(
|
||||||
extract_key_value_check(H, P) end,
|
fun(P) ->
|
||||||
PositionList),
|
FilterFalseKey(extract_key_value_check(H, P)) end,
|
||||||
{reply, KVCList, reader, State}
|
PositionList)
|
||||||
end;
|
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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue