Skip to content

Commit f8b4dde

Browse files
committed
fix: when decoding an invalid time range the decoder will use max/min values
1 parent 8a220b2 commit f8b4dde

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

lib/bson/decoder.ex

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,14 @@ defmodule BSON.DecoderGenerator do
66
use BSON.Utils
77
alias BSON.Decimal128
88

9+
require Logger
10+
911
@preserve_order opts[:preserve_order] || false
1012
@compile {:inline, cstring: 1}
13+
@max_unix_time ~U[9999-12-31 23:59:59.999Z]
14+
@min_unix_time ~U[-9999-01-01 00:00:00.000Z]
15+
@unix_start DateTime.to_unix(@min_unix_time, :millisecond)
16+
@unix_end DateTime.to_unix(@max_unix_time, :millisecond)
1117

1218
def decode(binary) do
1319
{map, ""} = document(binary)
@@ -128,7 +134,18 @@ defmodule BSON.DecoderGenerator do
128134
end
129135

130136
defp type(@type_datetime, <<unix_ms::int64(), rest::binary>>) do
131-
{DateTime.from_unix!(unix_ms, :millisecond), rest}
137+
cond do
138+
unix_ms < @unix_start ->
139+
Logger.warning("Invalid unix time: #{inspect(unix_ms)}, converted to #{inspect(@min_unix_time)}")
140+
{@min_unix_time, rest}
141+
142+
unix_ms > @unix_end ->
143+
Logger.warning("Invalid unix time: #{inspect(unix_ms)}, converted to #{inspect(@max_unix_time)}")
144+
{@max_unix_time, rest}
145+
146+
true ->
147+
{DateTime.from_unix!(unix_ms, :millisecond), rest}
148+
end
132149
end
133150

134151
defp type(@type_undefined, rest) do

test/bson/encoder_test.exs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,9 @@ defmodule BSON.EncoderTest do
44
test "return error in the case of encoder issues" do
55
assert_raise Mongo.Error, fn -> %{message: "invalid document: {:error, \"some error\"}"} = BSON.encode(%{"field" => {:error, "some error"}}) end
66
end
7+
8+
test "while decoding use max unix time range for invalid time ranges" do
9+
assert %{"ts" => ~U[9999-12-31 23:59:59.999Z]} == BSON.decode([<<17, 0, 0, 0>>, ["", 9, ["ts", 0], <<6_312_846_085_200_000::signed-little-64>>], 0])
10+
assert %{"ts" => ~U[-9999-01-01 00:00:00.000Z]} == BSON.decode([<<17, 0, 0, 0>>, ["", 9, ["ts", 0], <<-6_312_846_085_200_000::signed-little-64>>], 0])
11+
end
712
end

0 commit comments

Comments
 (0)