Skip to content

Commit

Permalink
Restrict looping over some map types
Browse files Browse the repository at this point in the history
It doesn't make sense to loop over these types:
- avg
- stats
- hist
- lhist

This is because these maps have complex values and keys,
which don't work for iteration. Example:
```
$ sudo ./src/bpftrace -e 'BEGIN { @x[1] = avg(5); for ($kv : @x) { print(($kv.0, $kv.1)); } exit(); }'
Attaching 1 probe...
(1, )
(1, )

@x[1]: 5
```
  • Loading branch information
Jordan Rome authored and viktormalik committed Jun 12, 2024
1 parent 5f696cb commit 1a04f18
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/ast/passes/semantic_analyser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2080,6 +2080,12 @@ void SemanticAnalyser::visit(For &f)
}
Map &map = static_cast<Map &>(*f.expr);

if (!map.type.IsMapIterableTy()) {
LOG(ERROR, f.expr->loc, err_)
<< "Loop expression does not support type: " << map.type;
return;
}

// Validate body
CollectNodes<Variable> vars_referenced;
for (auto *stmt : *f.stmts) {
Expand Down
5 changes: 5 additions & 0 deletions src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,11 @@ class SizedType {
return type_ == Type::count || type_ == Type::sum || type_ == Type::max ||
type_ == Type::min;
}
bool IsMapIterableTy() const
{
return !(type_ == Type::avg || type_ == Type::hist ||
type_ == Type::lhist || type_ == Type::stats);
}

friend std::ostream &operator<<(std::ostream &, const SizedType &);
friend std::ostream &operator<<(std::ostream &, Type);
Expand Down
25 changes: 25 additions & 0 deletions tests/semantic_analyser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3542,6 +3542,31 @@ BEGIN { @map[0] = 1; for ($kv : @undef) { @map[$kv.0]; } }
)");
}

TEST(semantic_analyser, for_loop_map_restricted_types)
{
test_error("BEGIN { @map[0] = avg(1); for ($kv : @map) { } }", R"(
stdin:1:38-43: ERROR: Loop expression does not support type: avg
BEGIN { @map[0] = avg(1); for ($kv : @map) { } }
~~~~~
)");
test_error("BEGIN { @map[0] = hist(10); for ($kv : @map) { } }", R"(
stdin:1:40-45: ERROR: Loop expression does not support type: hist
BEGIN { @map[0] = hist(10); for ($kv : @map) { } }
~~~~~
)");
test_error("BEGIN { @map[0] = lhist(10, 0, 10, 1); for ($kv : @map) { } }",
R"(
stdin:1:51-56: ERROR: Loop expression does not support type: lhist
BEGIN { @map[0] = lhist(10, 0, 10, 1); for ($kv : @map) { } }
~~~~~
)");
test_error("BEGIN { @map[0] = stats(10); for ($kv : @map) { } }", R"(
stdin:1:41-46: ERROR: Loop expression does not support type: stats
BEGIN { @map[0] = stats(10); for ($kv : @map) { } }
~~~~~
)");
}

TEST(semantic_analyser, for_loop_shadowed_decl)
{
test_error(R"(
Expand Down

0 comments on commit 1a04f18

Please sign in to comment.