Skip to content

Conversation

@tamird
Copy link
Contributor

@tamird tamird commented Jun 9, 2025

Summary:

Previously, Result<T>'s constructor used std::move(val) to initialize the
value. This resulted in an unnecessary extra move and destructor call on a
moved-from stack object, triggering an HWASAN stack tag mismatch when the
moved-from object was later destructed.

Replacing std::move(val) with std::forward<T>(val) avoids the extra move
while preserving correct semantics. This ensures only one move occurs and
avoids lifetime violations that can lead to tag mismatches under HWASAN.

Differential Revision: D76271359

@pytorch-bot
Copy link

pytorch-bot bot commented Jun 9, 2025

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/11485

Note: Links to docs will display an error until the docs builds have been completed.

✅ No Failures

As of commit 2c6361e with merge base 611092d (image):
💚 Looks good so far! There are no failures yet. 💚

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jun 9, 2025
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D76271359

@tamird
Copy link
Contributor Author

tamird commented Jun 9, 2025

@pytorchbot label "release notes: none"

@pytorch-bot pytorch-bot bot added the release notes: none Do not include this in the release notes label Jun 9, 2025
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D76271359

1 similar comment
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D76271359

@tamird tamird changed the title Use std::forward to avoid immediate trivial move Avoid use-after-return caused by double move Jun 9, 2025
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D76271359

1 similar comment
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D76271359

Summary:
Previously, `Result<T>`'s constructor used `std::move(val)` to initialize the
value. This resulted in an unnecessary extra move and destructor call on a
moved-from stack object, triggering an HWASAN stack tag mismatch when the
moved-from object was later destructed.

Replacing `std::move(val)` with `std::forward<T>(val)` avoids the extra move
while preserving correct semantics. This ensures only one move occurs and
avoids lifetime violations that can lead to tag mismatches under HWASAN.

Reviewed By: StefanBossbaly

Differential Revision: D76271359
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D76271359

Copy link
Contributor

@JacobSzwejbka JacobSzwejbka left a comment

Choose a reason for hiding this comment

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

Thanks for the catch!

/* implicit */ Result(T&& val) : value_(std::move(val)), hasValue_(true) {}
/// Value forwarding constructor.
/* implicit */ Result(T&& val)
: value_(std::forward<T>(val)), hasValue_(true) {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add a test that wouldve caught the previous bad behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure. Where are the tests for this type?

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

@swolchok swolchok left a comment

Choose a reason for hiding this comment

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

looks great, needs test, happy to accept with the test

@tamird
Copy link
Contributor Author

tamird commented Jun 9, 2025

looks great, needs test, happy to accept with the test

I tried writing a test, but I have failed to induce the problematic behavior. I think it shows up only in the presence of stack tagging as performed by hwasan.

Comment on lines -73 to +75
/// Value move constructor.
/* implicit */ Result(T&& val) : value_(std::move(val)), hasValue_(true) {}
/// Value forwarding constructor.
/* implicit */ Result(T&& val)
: value_(std::forward<T>(val)), hasValue_(true) {}
Copy link
Contributor

Choose a reason for hiding this comment

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

I misread what was going on here originally. This isn't a template function (though it is a member of a template class), so this really is an rvalue reference. I think that the original code is probably correct; std::forward is for arguments to template functions (https://en.cppreference.com/w/cpp/utility/forward.html).

@tamird
Copy link
Contributor Author

tamird commented Jun 11, 2025

This turned out to be a red herring.

@tamird tamird closed this Jun 11, 2025
@tamird tamird deleted the export-D76271359 branch June 11, 2025 17:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. fb-exported release notes: none Do not include this in the release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants