Packages

Validate quoted Elixir AST against a function whitelist

Current section

Files

Jump to
loppers lib match.ex
Raw

lib/match.ex

defmodule Loppers.Match do
def matches?({function, context, _args}, function) do
!Keyword.has_key?(context, :import) and !Keyword.has_key?(context, :alias)
end
# alias Enum, as: E
# E.map(:a, :b)
# {
# {:., [], [{:__aliases__, [alias: Enum], [:E]}, :map]},
# [],
# [:a, :b]}
# ABC.fun(1, 2, 3)
# {{:., [], [{:__aliases__, [alias: false], [:ABC]}, :fun]}, [], [1, 2, 3]}
def matches?({{:., _dot_meta, [{:__aliases__, aliases, called_as}, called_fn]}, _fn_meta, arguments}, {mod, list_fn})
when called_fn == list_fn or list_fn == :__all__ do
called_module = case Keyword.get(aliases, :alias, false) do
false -> list_to_module(called_as)
aliased_module -> aliased_module
end
mod == called_module
end
# special case for calling erlang module functions
def matches?({{:., _dot_context, [erlang_module, called_fn]}, _fn_context, arguments}, {mod, list_fn})
when (called_fn == list_fn or list_fn == :__all__)
and erlang_module == mod do
true
end
# import Enum
# map(:a, :b)
# {:map, [context: Elixir, import: Enum], [:a, :b]}
def matches?({function, context, arguments}, {mod, function}) do
called_module = Keyword.get(context, :import)
mod == called_module
end
def matches?(_, _) do
false
end
def is_fn?(ast) when not is_tuple(ast), do: false
def is_fn?({:__aliases__, _, _}), do: false
def is_fn?({_variable, context, nil}) do
Keyword.has_key?(context, :alias) or Keyword.has_key?(context, :import)
end
def is_fn?({:__ENV__, _, _}), do: false
def is_fn?({:__block__, _, _}), do: false
def is_fn?({:do, _}), do: false
def is_fn?(_), do: true
def list_to_module([:erlang, mod]), do: mod
def list_to_module(list) do
[:Elixir | list]
|> Enum.map(&Atom.to_string/1)
|> Enum.join(".")
|> String.to_atom
end
end