Skip to content

Sentry.Event.transform_exception can allocate huge amounts of memory #881

@bmteller

Description

@bmteller

I think this is actually a bug with how Elixir works because Exception.message is an unsafe method to call in production systems and should really be only used for debugging but it is not documented as such.

So some internal Elixir implementation of Exception.message will cause inspect to generate a pretty string for arbitrary data. For example KeyError that is produced when you call Map.fetch! and the key is missing (https://github.com/elixir-lang/elixir/blob/b1cbe7adc9930ab00dbb668a41053d35381a2344/lib/elixir/lib/exception.ex#L2187).

The inspect method has limits but these limits are based on size of strings and the number of sub elements to print. Importantly there is no limit to the depth [!!!!!!!!!] of a tree that inspect might try to print. Also, inspect offers no option to limit the total size of the output which is probably the main thing callers want to protect against when inspecting terms that may be of arbitrary size. Of course just limiting the total output may not be enough if you have a tree of terms that produce no output since inspect now may spend a lot of time traversing a tree structure that you have not budgeted for but I suspect this is a pathological case.

Here is an example:

big = fn(y, d, n) -> if d == 0 do; []; else; Enum.map(1..n, fn(_) -> y.(y, d - 1, n) end) end end
evil_map = %{"hello" => big.(big, 7, 5)}; 1
evil_exception = try do; Map.fetch!(evil_map, "world"); rescue e -> e; end; 1
byte_size(Exception.message(evil_exception))

> 668008

In our case Exception.message produces a very large string and then somewhere else in Sentry this causes a large allocation which OOMs the erlang VM. Maybe it is possible as a short term fix to add an option to truncate the output of Exception.message to something sensible to decrease the chance of Sentry OOMing the VM.

Just to add:

  • there is a similar problem in __STACKTRACE__ which sentry uses in the capture plug: https://github.com/getsentry/sentry-elixir/blob/master/lib/sentry/plug_capture.ex#L112 . for some reason in some situations the arguments of the method raising an exception will be included in the stack trace. If one of these arguments is large then sentry might create a huge event.
  • After creating this event of doom Sentry.Transporter.Sender will likely leak the memory for a long time due to way erlang process garbage collection works.

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    Waiting for: Product Owner

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions