Skip to content

fix(rocprofiler-compute): restrict metric expression evaluation#8918

Open
fjankovi wants to merge 7 commits into
developfrom
users/fjankovi/fix-rocprofiler-compute-metric-eval
Open

fix(rocprofiler-compute): restrict metric expression evaluation#8918
fjankovi wants to merge 7 commits into
developfrom
users/fjankovi/fix-rocprofiler-compute-metric-eval

Conversation

@fjankovi

@fjankovi fjankovi commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Motivation

Metric expressions loaded from profiling workspaces were evaluated using
Python eval(). Supplying an empty globals dictionary still exposed Python
builtins, allowing a crafted workspace configuration to execute arbitrary
code in the analyst's account.

Technical Details

  • Add a restricted AST interpreter for metric expressions.
  • Allow only supported arithmetic, comparisons, scalar conditionals,
    approved dataframe and system-information lookups, whitelisted metric
    helper functions, and pandas.Series.where.
  • Reject imports, arbitrary function and method calls, attribute traversal,
    dynamic subscripts, callable runtime values, and overly complex expressions.
  • Replace eval() in both the standard metric evaluator and analysis database
    evaluator.
  • Add regression coverage for code-execution payloads and unsupported Python
    language features.

Issue Tracking

JIRA ID: SWSPLAT-24278

Test Plan

  • Run Ruff lint and formatting checks on all changed Python files.
  • Run metric evaluator, analysis database, parser, and division-by-zero tests.
  • Compile all changed Python files.
  • Scan the source AST for remaining eval() or exec() calls.

Test Result

  • Ruff lint: passed
  • Ruff formatting: passed
  • Python compilation: passed
  • Unit tests: 176 passed
  • Source scan: no eval() or exec() calls found

Submission Checklist

  • Looked over the contributing guidelines.

Replace Python eval calls in metric evaluation with a restricted AST interpreter that only permits supported arithmetic, data lookups, aggregation helpers, and Series.where.

Reject imports, arbitrary calls and attributes, dynamic subscripts, and overly complex expressions. Add regression coverage for code-execution payloads in both analyzer paths.
Copilot AI review requested due to automatic review settings July 21, 2026 12:40
@fjankovi
fjankovi requested a review from a team as a code owner July 21, 2026 12:40
@therock-pr-bot

therock-pr-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown

✅ All Checks Passed — Ready for Review

Check Status Details
🌿 Branch Name ✅ Pass
📝 PR Title/Description ✅ Pass
Forbidden Files ✅ Pass
🧪 Unit Test ✅ Pass
🔎 pre-commit ✅ Pass
🚫 Draft PR 🔜 To Be Enabled
🚩 Feature Flag 🔜 To Be Enabled
📊 Code Coverage 🔜 To Be Enabled
🤖 therock-pr-bot ✅ Pass

🎉 All checks passed! This PR is ready for review.

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens rocprofiler-compute’s metric/expression evaluation by replacing Python eval() with a restricted AST-based interpreter, preventing workspace-supplied expressions from executing arbitrary code in the analyst’s environment.

Changes:

  • Introduces utils.metrics.safe_expression.evaluate_expression() as a restricted evaluator for metric expressions.
  • Replaces eval() usage in both the YAML metric evaluator and analysis DB evaluator with the restricted evaluator.
  • Adds regression tests ensuring code-execution payloads and disallowed Python constructs are rejected.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
projects/rocprofiler-compute/tests/test_metric_utils.py Adds unit tests for the restricted expression evaluator and updates MetricEvaluator tests to patch evaluate_expression.
projects/rocprofiler-compute/tests/test_analysis_db.py Adds regression test asserting analysis DB expression evaluation can’t execute Python payloads.
projects/rocprofiler-compute/src/utils/metrics/safe_expression.py Adds the new restricted AST evaluator implementation.
projects/rocprofiler-compute/src/utils/metrics/metric_evaluator.py Switches metric evaluation from eval() to evaluate_expression with a function whitelist.
projects/rocprofiler-compute/src/utils/metrics/evaluation_pipeline.py Removes obsolete commented-out eval() experimentation.
projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_db.py Switches analysis DB expression evaluation from eval() to evaluate_expression.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread projects/rocprofiler-compute/src/utils/metrics/safe_expression.py Outdated
Comment thread projects/rocprofiler-compute/src/utils/metrics/safe_expression.py Outdated
@therock-pr-bot

Copy link
Copy Markdown

🎉 All checks passed! This PR is ready for review.

Limit metric expressions to the condition and optional other arguments supported by the safe expression language. Reject extra positional arguments before evaluation and cover the mutation case with a regression test.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Translate RecursionError from parsing or recursive AST evaluation into UnsafeExpressionError so analyzer callers continue to return N/A or None. Add regression coverage for expressions below the node limit that exceed Python's recursion depth.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Comment thread projects/rocprofiler-compute/tests/test_metric_utils.py Outdated
Set a known recursion limit only around deep-expression evaluation and restore the process setting afterward. Count AST nodes before lowering the limit so the test remains deterministic across runner configurations.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Comment thread projects/rocprofiler-compute/src/utils/metrics/safe_expression.py Outdated
@fjankovi
fjankovi marked this pull request as draft July 21, 2026 15:17
Disallow binary arithmetic on scalar strings and string-containing Series to prevent workspace expressions from amplifying small inputs into excessive allocations. Preserve numeric object-Series arithmetic and cover scalar, NumPy-integer, concatenation, and Series cases.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Comment thread projects/rocprofiler-compute/src/utils/metrics/safe_expression.py
Comment thread projects/rocprofiler-compute/src/utils/metrics/metric_evaluator.py
fjankovi and others added 2 commits July 21, 2026 17:48
Reject non-scalar conditional tests before truth-value conversion and translate ambiguous scalar values into UnsafeExpressionError. Preserve scalar Python truthiness and add coverage for Series, arrays, containers, pd.NA, and valid scalar conditions.
@fjankovi
fjankovi marked this pull request as ready for review July 21, 2026 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants