Current section

Files

Jump to
sobelow lib sobelow finding.ex
Raw

lib/sobelow/finding.ex

defmodule Sobelow.Finding do
defstruct [
:type,
:confidence,
:filename,
:vuln_line_no,
:vuln_variable,
:vuln_source,
:fun_name,
:fun_line_no,
:fun_source,
:fingerprint
]
alias Sobelow.Utils
def init(type, filename, confidence \\ nil) do
%Sobelow.Finding{
type: type,
filename: filename,
confidence: confidence
}
end
def multi_from_def(%Sobelow.Finding{} = finding, fun, {vulns, params, {fun_name, fun_line_no}}) do
finding = %{finding | fun_name: fun_name, fun_line_no: fun_line_no, fun_source: fun}
Enum.map(vulns, fn {vuln, var} ->
%{
finding
| vuln_variable: var,
vuln_source: vuln,
vuln_line_no: Sobelow.Parse.get_fun_line(vuln),
confidence: Sobelow.Print.get_sev(params, var, finding.confidence)
}
|> normalize()
end)
end
def fetch_fingerprint(%Sobelow.Finding{} = finding) do
%{finding | fingerprint: fingerprint(finding)}
end
def fingerprint(%Sobelow.Finding{} = finding) do
filename =
Utils.get_root()
|> Utils.normalize_path()
|> (&String.replace_prefix(finding.filename, &1, "")).()
|> Utils.normalize_path()
[finding.type, finding.vuln_source, filename, finding.vuln_line_no]
|> :erlang.term_to_binary()
|> :erlang.md5()
|> Base.encode16()
end
defp normalize(%Sobelow.Finding{vuln_variable: vars} = finding) when is_list(vars) do
var = if length(vars) > 1, do: Enum.join(vars, " and "), else: hd(vars)
%{finding | vuln_variable: var} |> normalize()
end
defp normalize(%Sobelow.Finding{fun_source: fun} = finding) when is_list(fun) do
%{finding | fun_source: List.first(fun)} |> normalize()
end
defp normalize(finding), do: finding
defmacro __using__(_) do
quote do
alias Sobelow.Finding
alias Sobelow.Parse
alias Sobelow.Print
alias Sobelow.Utils
def details() do
IO.ANSI.Docs.print(@moduledoc, [])
end
defoverridable details: 0
end
end
end
defmodule Sobelow.FindingType do
defmacro __using__(_) do
quote do
def details() do
Enum.each(@submodules, fn sub ->
apply(sub, :details, [])
end)
end
defoverridable details: 0
end
end
end