Validate scale factor override to prevent panic on invalid values#23340
Validate scale factor override to prevent panic on invalid values#23340omar-y-abdi wants to merge 2 commits into
Conversation
|
Welcome, new contributor! Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨ |
alice-i-cecile
left a comment
There was a problem hiding this comment.
It's a bit unusual to have validation on the getters, but given that you can mess with these values via reflection / inspectors, I think it's defensible here.
Tests are a bit overkill, but I'm fine with them. They should all be fast to run.
mockersf
left a comment
There was a problem hiding this comment.
getters should not not return their value
Fixes bevyengine#23141. Setting `Window::scale_factor_override` to an invalid value (0.0, NaN, negative, infinity, subnormal) caused a panic in winit's `dpi` crate. This adds validation at both the setter and getter level: - `set_scale_factor_override` warns and rejects invalid values - `scale_factor()` and `scale_factor_override()` filter out invalid values as defense-in-depth against Reflect bypass
…er feedback - Getters now return stored values directly without filtering - Validation remains in setters only, with doc comments explaining that invalid values are ignored with a warning - Simplified scale factor docs: "must be greater than zero" - Consolidated 10 individual scale factor tests into one
826cee0 to
0b144ae
Compare
|
I don't know if my PR still has an issue to resolve or if another PR has solved it already. If my PR fixes an issue that is still relevant, please feel free to write a review saying what needs to change and i'll commit changes based on your feedback. |
|
You should update your PR description :) |
tbillington
left a comment
There was a problem hiding this comment.
In hindsight I don't know if this actually fixes the original issue. I triggered the panic by setting the value through egui inspector which uses bevy_reflect, so I assume set_scale_factor_override was never actually called, and it was just the fact that the Window had been mutated which triggered bevy to update winit with the new values, completely bypassing set_scale_factor_override.
Were you able replicate the original issue and confirm this PR fixed it?
I opened the initial issue more to get inputs from other people on what is the ideal way to solve it and not just to get it fixed asap. I included the reproduction steps of the panic in the issue description, but presented multiple options on how we might solve it. I didn't try to raise a fix PR myself because I wanted to get community consensus on what behaviour we actually want in a situation like this. I also wasn't 100% sure what the correct way to fix it was. It's a niche issue in Bevy today so there was no rush to fix it. But I should have been more explicit about that intention, that's my fault.
Er also you didn't reply to my question about using winit's validation function and just marked it as resolved 😛 . It's usually best to stick to the same logic if possible, but if you have some concerns with it we can help with them. Did you not want to use it for some reason?
Objective
Window::scale_factor_overrideto an invalid value (e.g.0.0,NaN, negative, infinity, subnormal) crashes the engine with a panic in winit'sdpicrate:assertion failed: validate_scale_factor(scale_factor)bevy_inspector_egui, where changingNonetoSome(x)defaults to0.0Solution
Added scale factor validation at three points in
WindowResolution(crates/bevy_window/src/window.rs):set_scale_factor_override()— rejects invalid values with awarn!log and early return, matching the existingcheck_constraintspattern used for window resize constraintsscale_factor()getter — filters out invalid overrides via.filter(), falling back tobase_scale_factor(). This is defense-in-depth sinceWindowResolutionderivesReflect, allowing inspector tools to bypass the setterscale_factor_override()getter — same.filter()guard, ensuring all downstream consumers inbevy_winit(window creation,changed_windowssystem) receive valid values orNoneA scale factor is valid when
f32::is_normal() && > 0.0, matching winit's ownvalidate_scale_factorcriteria.A private helper
is_valid_scale_factor(f32) -> boolcentralizes the check across all three call sites.Testing
None(to clear override)cargo test -p bevy_window— 13 tests pass (11 new + 2 existing)cargo clippy -p bevy_window -- -D warnings— clean