Skip to content

Only Use Result From get_helper_prototype when valid#1050

Merged
elazarg merged 1 commit intovbpf:mainfrom
hawkinsw:get_helper_prototype_use_fix
Mar 10, 2026
Merged

Only Use Result From get_helper_prototype when valid#1050
elazarg merged 1 commit intovbpf:mainfrom
hawkinsw:get_helper_prototype_use_fix

Conversation

@hawkinsw
Copy link
Contributor

@hawkinsw hawkinsw commented Mar 10, 2026

In the case where the result EbpfHelperPrototype's name is null, do not attempt to use it.

Summary by CodeRabbit

  • Bug Fixes
    • Replaced exception-driven handling for unavailable platform helpers with a safe, non-throwing fallback that yields a neutral prototype when a helper is not usable.
    • Error reporting and call handling are now consistent and user-friendly: unavailable helpers are reported by name (or numeric fallback), marked as unsupported, and no longer cause unexpected failures.

@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Unmarshal now uses a prototype-derived name when available instead of throwing; Linux helper lookup (get_helper_prototype_linux) no longer throws for unusable helper indices and returns a default-constructed EbpfHelperPrototype instead.

Changes

Cohort / File(s) Summary
Unmarshaller changes
src/ir/unmarshal.cpp
Use a local helper_prototype_name (prototype name or numeric fallback) for exposed names and error messages; change call/jump paths to produce unsupported Call values using prototype-derived name when helpers are unusable rather than relying on exceptions.
Linux helper prototype lookup
src/linux/gpl/spec_prototypes.cpp
get_helper_prototype_linux no longer throws when is_helper_usable_linux(n) is false; returns a default-constructed EbpfHelperPrototype instead. Signature unchanged.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly describes the main change: preventing use of results from get_helper_prototype when they are invalid (null), which aligns with the core objective of avoiding crashes from null prototype names.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/ir/unmarshal.cpp`:
- Around line 706-709: The code calls
info.platform->get_helper_prototype(inst.imm) twice and discards the validated
pointer; replace the second lookup by assigning the already-checked value: set
name = name_from_helper_prototype when name_from_helper_prototype is truthy
instead of calling get_helper_prototype(inst.imm) again. Update the block around
name_from_helper_prototype, get_helper_prototype, inst.imm, and name to reuse
the first result.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: cc152546-85f9-40d1-8e0b-a1633a3e5ff0

📥 Commits

Reviewing files that changed from the base of the PR and between b24faf5 and d7fe4d9.

📒 Files selected for processing (1)
  • src/ir/unmarshal.cpp

@hawkinsw
Copy link
Contributor Author

First, thank you for doing such awesome work on this verifier! I work with @Alan-Jowett and we use the verifier in our uBPF implementation. We have a configuration for fuzzing that does not do any meaningful work in the platform abstraction functions (e.g., get_helper_prototype). As a result, we were seeing crashes in the verifier when it attempted to build a std::string from the nullptr in .name in EbpfHelperPrototype.

Another potential fix for the issue is for us to make sure that we throw (so that your try saves the day!) and then update the documentation to indicate where such throws are required in the platform abstraction function. If you would prefer that type of fix, please let me know! I would be more than happy to do that!

Thank you, again, for the great work!!

@hawkinsw hawkinsw force-pushed the get_helper_prototype_use_fix branch from d7fe4d9 to fc23bfd Compare March 10, 2026 12:04
@hawkinsw hawkinsw force-pushed the get_helper_prototype_use_fix branch from fc23bfd to c1a39ad Compare March 10, 2026 12:43
@hawkinsw
Copy link
Contributor Author

Also, I am not 100% sure of the semantics that you are looking for here, but it seems like the conditional around this code might be backward.

I see

            if (!info.platform->is_helper_usable(inst.imm)) {

and the code being guarded then attempts to use the helper. It's possible that is the real issue here?!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/ir/unmarshal.cpp (1)

493-496: 🧹 Nitpick | 🔵 Trivial

Invariant assumption: is_helper_usable(n)get_helper_prototype(n).name != nullptr

Line 496 assigns proto.name to a std::string without a null check. This is safe given the current control flow (only called after is_helper_usable returns true at line 703), but the soundness relies on platform implementations maintaining this invariant.

Per coding guidelines about encoding assumptions explicitly, consider adding an assertion or defensive check:

Suggested defensive assertion
 auto makeCall(const int32_t imm) const -> Call {
     const EbpfHelperPrototype proto = info.platform->get_helper_prototype(imm);
+    assert(proto.name != nullptr && "get_helper_prototype returned null name for usable helper");
     Call res;
     res.func = imm;
     res.name = proto.name;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ir/unmarshal.cpp` around lines 493 - 496, The code assigns proto.name
(from EbpfHelperPrototype returned by get_helper_prototype) to a std::string
without checking for null, relying on the implicit invariant guaranteed by
is_helper_usable; add an explicit defensive check or assertion to encode that
invariant: validate that proto.name is non-null (or assert is_helper_usable(imm)
/ proto.name != nullptr) before assigning to res.name and handle the failure
path (e.g., log/error/abort) so the contract is enforced at runtime; reference
get_helper_prototype, EbpfHelperPrototype::name, is_helper_usable, and res.name
when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/ir/unmarshal.cpp`:
- Around line 493-496: The code assigns proto.name (from EbpfHelperPrototype
returned by get_helper_prototype) to a std::string without checking for null,
relying on the implicit invariant guaranteed by is_helper_usable; add an
explicit defensive check or assertion to encode that invariant: validate that
proto.name is non-null (or assert is_helper_usable(imm) / proto.name != nullptr)
before assigning to res.name and handle the failure path (e.g., log/error/abort)
so the contract is enforced at runtime; reference get_helper_prototype,
EbpfHelperPrototype::name, is_helper_usable, and res.name when making the
change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d86abd3a-38bc-44d3-82d1-772b92a1bd68

📥 Commits

Reviewing files that changed from the base of the PR and between fc23bfd and c1a39ad.

📒 Files selected for processing (2)
  • src/ir/unmarshal.cpp
  • src/linux/gpl/spec_prototypes.cpp

@elazarg
Copy link
Collaborator

elazarg commented Mar 10, 2026

Also, I am not 100% sure of the semantics that you are looking for here, but it seems like the conditional around this code might be backward.

I see

            if (!info.platform->is_helper_usable(inst.imm)) {

and the code being guarded then attempts to use the helper. It's possible that is the real issue here?!

Would be simpler to read:

if (info.platform->is_helper_usable(inst.imm)) {
    return makeCall(inst.imm);
}
// then your code

@hawkinsw
Copy link
Contributor Author

Also, I am not 100% sure of the semantics that you are looking for here, but it seems like the conditional around this code might be backward.
I see

            if (!info.platform->is_helper_usable(inst.imm)) {

and the code being guarded then attempts to use the helper. It's possible that is the real issue here?!

Would be simpler to read:

if (info.platform->is_helper_usable(inst.imm)) {
    return makeCall(inst.imm);
}
// then your code

That was the code that already existed. I was just pointing out that the existing code seems to be wrong. If you agree that the code (as it is currently) is wrong, then I would be more than happy to fix it!

@hawkinsw hawkinsw force-pushed the get_helper_prototype_use_fix branch from c1a39ad to c3d861a Compare March 10, 2026 13:31
@hawkinsw hawkinsw requested a review from elazarg March 10, 2026 13:32
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/ir/unmarshal.cpp`:
- Around line 703-714: Centralize the null-name guard by moving the logic that
checks for a missing helper prototype name into makeCall() so callers like
makeJmp() and any direct uses of makeCall()/make_call() never receive a Call
with an empty or null name; specifically, inside makeCall() check the result of
info.platform->get_helper_prototype(inst.imm) (or its proto.name) and if missing
return a Call with is_supported=false and unsupported_reason set, otherwise
assign proto.name to Call::name and mark supported; remove the duplicate
fallback in the makeJmp() path and ensure get_helper_prototype() remains
unchanged unless you convert it to return an optional/explicit error type.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8f8a88b6-cc0e-4124-b473-4e108544f5a3

📥 Commits

Reviewing files that changed from the base of the PR and between c1a39ad and c3d861a.

📒 Files selected for processing (2)
  • src/ir/unmarshal.cpp
  • src/linux/gpl/spec_prototypes.cpp

@hawkinsw hawkinsw force-pushed the get_helper_prototype_use_fix branch 2 times, most recently from ed5dea9 to a362bb9 Compare March 10, 2026 15:04
In the case where the result EbpfHelperPrototype's name is null,
do not attempt to use it. Also, remove try/catch protection and make
sure that existing users of the get_helper_prototype platform
abstraction function do not rely on it.

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
@hawkinsw hawkinsw force-pushed the get_helper_prototype_use_fix branch from a362bb9 to 2171cb5 Compare March 10, 2026 15:05
@elazarg
Copy link
Collaborator

elazarg commented Mar 10, 2026

Also, I am not 100% sure of the semantics that you are looking for here, but it seems like the conditional around this code might be backward.
I see

            if (!info.platform->is_helper_usable(inst.imm)) {

and the code being guarded then attempts to use the helper. It's possible that is the real issue here?!

Would be simpler to read:

if (info.platform->is_helper_usable(inst.imm)) {
    return makeCall(inst.imm);
}
// then your code

That was the code that already existed. I was just pointing out that the existing code seems to be wrong. If you agree that the code (as it is currently) is wrong, then I would be more than happy to fix it!

makeCall also uses info.platform->get_helper_prototype(imm). If your issue is the repetition then you can propose an alternative, but I do not think it's incorrect.

@hawkinsw
Copy link
Contributor Author

Also, I am not 100% sure of the semantics that you are looking for here, but it seems like the conditional around this code might be backward.
I see

            if (!info.platform->is_helper_usable(inst.imm)) {

and the code being guarded then attempts to use the helper. It's possible that is the real issue here?!

Would be simpler to read:

if (info.platform->is_helper_usable(inst.imm)) {
    return makeCall(inst.imm);
}
// then your code

That was the code that already existed. I was just pointing out that the existing code seems to be wrong. If you agree that the code (as it is currently) is wrong, then I would be more than happy to fix it!

makeCall also uses info.platform->get_helper_prototype(imm). If your issue is the repetition then you can propose an alternative, but I do not think it's incorrect.

Okay! Let me know what you think of the PR in its current state.

@elazarg elazarg merged commit 6f0384e into vbpf:main Mar 10, 2026
16 checks passed
@hawkinsw
Copy link
Contributor Author

Thanks for accepting, @elazarg !! I hope I can contribute more in the future!! It's great to work with people like you!

@elazarg
Copy link
Collaborator

elazarg commented Mar 10, 2026

@hawkinsw you're welcome. Thanks for the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants