src/rules/suspicious/table.bend checks
raw source on the hub · import 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/rules/suspicious/table.bend as Table
rule table: List.get or List.set at a computed index inside a def that
calls itself, when the list is a fixed table: a literal, an array, or
List.replicate / Array.new / List.range with a constant count, written
inline, defined beside the loop, or held by the let of that name in scope.
The index walks that table on every step. Keep it in an Array. A let reaches
the statements after it and the blocks under them, not a sibling case arm,
and a later let of the name to anything else ends it. A literal index (a
fixed slot, including 0 and 1), a growing or data-dependent list, a one-shot
outside the recursion, and List.head / List.tail do not run. index
leaves a table this rule owns, so one call is one finding. Laws and proofs
do not run (a def with no type at all fills a law: it is a proof).
7 imports
import Base import ../../src.bend as Src import ../../finding.bend as F import ../../syntax/lex.bend as Lex import ../../syntax/tree.bend as Tree import ../calls.bend as Calls import ../../lazy/lazy.bend as Lazy
Definitions
def literal source · line 21 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> Bool
is the chain exactly one number?
def top_has source · line 29 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> @+want:String -> Bool
a top-level token of this text, not one nested in a group
def array_sized source · line 42 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> Bool
[v : T*n] or [v : T^d], and the size is a number
def lone_num source · line 57 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> Bool
the chain is exactly one number
def range_count source · line 65 · raw
@as:List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node> -> Bool
List.replicate / Array.new count at argument 2; List.range at the end
def built_call source · line 75 · raw
@+tt:String -> @kids:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> Bool
a constant-size constructor, not a length taken from the data
def built source · line 81 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> Bool
a list literal, a sized array, or a constant-size constructor
def call_name source · line 92 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> String
the chain is exactly this call's name, with no arguments that matter: name()
def lone_name source · line 101 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> String
the chain is exactly one lowercase name
def key source · line 109 · raw
@+tt:String -> @+line:U32 -> @+col:U32 -> String
one use of a name, told apart from its other uses by where it stands
def lone_key source · line 113 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> String
the chain is exactly one lowercase name: that use's key
def owns source · line 122 · raw
@+nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> @+fixed:List<&2, String> -> Bool
the list argument is a fixed table: inline, a use of a let that holds one,
or name() / name for a table def of the file
def bind_bad source · line 132 · raw
@+bad:Bool -> @+nm:String -> String
one plain name before =, when the pattern is not a destructure
def bind_at source · line 140 · raw
@+seen:Bool -> @+bad:Bool -> @+nm:String -> String
one plain name before =, when there is one
def bind_name source · line 148 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> @+seen:Bool -> @+bad:Bool -> @+nm:String -> String
the one plain name a statement binds, or empty
def bind_rhs source · line 164 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node
the right-hand side: the chain after a statement's top-level =
def drop source · line 174 · raw
@live:List<&2, String> -> @+nm:String -> List<&2, String>
the names in scope without this one
def rebind source · line 183 · raw
@+nm:String -> @+tab:Bool -> @+live:List<&2, String> -> List<&2, String>
after a let of nm: it holds a table only when this binding is one
def use_at source · line 189 · raw
@+tt:String -> @+line:U32 -> @+col:U32 -> @+live:List<&2, String> -> @+acc:List<&2, String> -> List<&2, String>
a name use joins the keys when the let in scope for it holds a table
def lets source · line 195 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> @+live:List<&2, String> -> @acc:List<&2, String> -> List<&2, String>
the keys of every name use under the node whose binding in scope is a table: a let reaches the statements after it and their bodies, not an enclosing block or a sibling arm, and a later let of the name replaces it
def mod_one source · line 210 · raw
@body:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> @+name:String -> @+acc:List<&2, String> -> List<&2, String>
a def whose body is one fixed table
def modules source · line 218 · raw
@ds:List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/rules/calls.Def> -> @acc:List<&2, String> -> List<&2, String>
defs of this file whose body is one fixed table
def scope source · line 227 · raw
@body:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> @+mods:List<&2, String> -> List<&2, String>
fixed tables visible in this def: the file's table defs by name, and each use of a let whose binding in scope is a table, by its key
def cite source · line 231 · raw
@+get:Bool -> @+path:String -> @+line:U32 -> @+col:U32 -> @+len:U32 -> 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding
the finding for a get or a set
def hit source · line 241 · raw
@+open:Bool -> @+tt:String -> @kids:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> @+fixed:List<&2, String> -> @+path:String -> @+line:U32 -> @+col:U32 -> List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>
a get or a set of a fixed table at a computed index
def walk source · line 259 · raw
@nn:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/syntax/tree.Node -> @+path:String -> @+fixed:List<&2, String> -> List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>
every fixed-table get or set
def check.go source · line 273 · raw
@ds:List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/rules/calls.Def> -> @+mods:List<&2, String> -> @+path:String -> @acc:List<&2, List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>> -> List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>
def check source · line 289 · raw
@ss:0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/src.Src -> List<&2, 0x582b4b0fdf3dafdeecc8c3bfddc5e4db/src/finding.Finding>
the rule