mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-04 13:30:48 +00:00
Fix crash from overflowing values given to NumberInput widgets (#1377)
* Added hints for brush tool size * Added hints for brush tool size * Solved the user being able to crash the editor by overflowing NumberInputs
This commit is contained in:
parent
1c11ebcc4e
commit
fd338c945f
16 changed files with 47 additions and 4 deletions
|
@ -94,6 +94,7 @@ impl LayoutHolder for ExportDialogMessageHandler {
|
|||
NumberInput::new(Some(self.scale_factor))
|
||||
.unit(" ")
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.disabled(self.file_type == FileType::Svg)
|
||||
.on_update(|number_input: &NumberInput| ExportDialogMessage::ScaleFactor(number_input.value.unwrap()).into())
|
||||
.widget_holder(),
|
||||
|
|
|
@ -75,6 +75,7 @@ impl LayoutHolder for NewDocumentDialogMessageHandler {
|
|||
.label("W")
|
||||
.unit(" px")
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.is_integer(true)
|
||||
.disabled(self.infinite)
|
||||
.min_width(100)
|
||||
|
@ -85,6 +86,7 @@ impl LayoutHolder for NewDocumentDialogMessageHandler {
|
|||
.label("H")
|
||||
.unit(" px")
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.is_integer(true)
|
||||
.disabled(self.infinite)
|
||||
.min_width(100)
|
||||
|
|
|
@ -58,6 +58,7 @@ impl PreferencesDialogMessageHandler {
|
|||
NumberInput::new(Some(preferences.imaginate_refresh_frequency))
|
||||
.unit(" seconds")
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.min_width(200)
|
||||
.on_update(|number_input: &NumberInput| PreferencesMessage::ImaginateRefreshFrequency { seconds: number_input.value.unwrap() }.into())
|
||||
.widget_holder(),
|
||||
|
|
|
@ -183,7 +183,7 @@ impl<F: Fn(&MessageDiscriminant) -> Vec<KeysGroup>> MessageHandler<LayoutMessage
|
|||
panic!("Invalid string found when updating `NumberInput`")
|
||||
}
|
||||
},
|
||||
_ => panic!("Invalid type found when updating `NumberInput`"),
|
||||
_ => {} // If it's some other type we could just ignore it and leave the value as is
|
||||
},
|
||||
Widget::OptionalInput(optional_input) => {
|
||||
let update_value = value.as_bool().expect("OptionalInput update was not of type: bool");
|
||||
|
|
|
@ -273,7 +273,6 @@ impl NumberInput {
|
|||
pub fn max(mut self, val: f64) -> Self {
|
||||
self.max = Some(val);
|
||||
self.range_max = Some(val);
|
||||
self.mode = NumberInputMode::Range;
|
||||
self
|
||||
}
|
||||
pub fn mode_range(mut self) -> Self {
|
||||
|
@ -289,7 +288,7 @@ impl NumberInput {
|
|||
self
|
||||
}
|
||||
pub fn percentage(self) -> Self {
|
||||
self.min(0.).max(100.).unit("%").display_decimal_places(2)
|
||||
self.min(0.).max(100.).mode_range().unit("%").display_decimal_places(2)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -144,12 +144,16 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
|
|||
NumberInput::new(Some(vec2.x))
|
||||
.label(x)
|
||||
.unit(unit)
|
||||
.min(-((1u64 << std::f64::MANTISSA_DIGITS) as f64))
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(input.value.unwrap(), vec2.y)), node_id, index))
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
NumberInput::new(Some(vec2.y))
|
||||
.label(y)
|
||||
.unit(unit)
|
||||
.min(-((1u64 << std::f64::MANTISSA_DIGITS) as f64))
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(vec2.x, input.value.unwrap())), node_id, index))
|
||||
.widget_holder(),
|
||||
]);
|
||||
|
@ -166,6 +170,8 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
|
|||
.int()
|
||||
.label(x)
|
||||
.unit(unit)
|
||||
.min(-((1u64 << std::f64::MANTISSA_DIGITS) as f64))
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(update_value(update_x, node_id, index))
|
||||
.widget_holder(),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
|
@ -173,6 +179,8 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
|
|||
.int()
|
||||
.label(y)
|
||||
.unit(unit)
|
||||
.min(-((1u64 << std::f64::MANTISSA_DIGITS) as f64))
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(update_value(update_y, node_id, index))
|
||||
.widget_holder(),
|
||||
]);
|
||||
|
@ -1756,7 +1764,7 @@ pub fn fill_properties(document_node: &DocumentNode, node_id: NodeId, _context:
|
|||
pub fn layer_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
let name = text_widget(document_node, node_id, 1, "Name", true);
|
||||
let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true);
|
||||
let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().min(0.).max(100.).unit("%"), true);
|
||||
let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().percentage(), true);
|
||||
let visible = bool_widget(document_node, node_id, 4, "Visible", true);
|
||||
let locked = bool_widget(document_node, node_id, 5, "Locked", true);
|
||||
let collapsed = bool_widget(document_node, node_id, 6, "Collapsed", true);
|
||||
|
|
|
@ -98,6 +98,8 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
|
|||
NumberInput::new(Some(layer.transform.x() + pivot.x))
|
||||
.label("X")
|
||||
.unit(" px")
|
||||
.min(1.)
|
||||
.max(std::i32::MAX as f64)
|
||||
.on_update(move |number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap() - pivot.x,
|
||||
|
@ -110,6 +112,8 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
|
|||
NumberInput::new(Some(layer.transform.y() + pivot.y))
|
||||
.label("Y")
|
||||
.unit(" px")
|
||||
.min(1.)
|
||||
.max(std::i32::MAX as f64)
|
||||
.on_update(move |number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap() - pivot.y,
|
||||
|
@ -137,6 +141,7 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
|
|||
.unit(" px")
|
||||
.is_integer(true)
|
||||
.min(1.)
|
||||
.max(std::i32::MAX as f64)
|
||||
.on_update(|number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap(),
|
||||
|
@ -151,6 +156,7 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
|
|||
.unit(" px")
|
||||
.is_integer(true)
|
||||
.min(1.)
|
||||
.max(std::i32::MAX as f64)
|
||||
.on_update(|number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap(),
|
||||
|
@ -301,6 +307,8 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
|
|||
NumberInput::new(Some(layer.transform.x() + pivot.x))
|
||||
.label("X")
|
||||
.unit(" px")
|
||||
.min(-((1u64 << std::f64::MANTISSA_DIGITS) as f64))
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(move |number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap() - pivot.x,
|
||||
|
@ -313,6 +321,8 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
|
|||
NumberInput::new(Some(layer.transform.y() + pivot.y))
|
||||
.label("Y")
|
||||
.unit(" px")
|
||||
.min(-((1u64 << std::f64::MANTISSA_DIGITS) as f64))
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(move |number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap() - pivot.y,
|
||||
|
@ -361,6 +371,8 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
|
|||
NumberInput::new(Some(layer.transform.scale_x()))
|
||||
.label("X")
|
||||
.unit("")
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap(),
|
||||
|
@ -373,6 +385,7 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
|
|||
NumberInput::new(Some(layer.transform.scale_y()))
|
||||
.label("Y")
|
||||
.unit("")
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap(),
|
||||
|
@ -394,6 +407,7 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
|
|||
NumberInput::new(Some(layer.bounding_transform(&render_data).scale_x()))
|
||||
.label("W")
|
||||
.unit(" px")
|
||||
.max((1u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap(),
|
||||
|
@ -406,6 +420,7 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La
|
|||
NumberInput::new(Some(layer.bounding_transform(&render_data).scale_y()))
|
||||
.label("H")
|
||||
.unit(" px")
|
||||
.max((1u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap(),
|
||||
|
@ -682,6 +697,7 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutGroup {
|
|||
NumberInput::new(Some(stroke.weight()))
|
||||
.is_integer(false)
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.unit(" px")
|
||||
.on_update(move |number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyStroke {
|
||||
|
@ -722,6 +738,7 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutGroup {
|
|||
NumberInput::new(Some(stroke.dash_offset()))
|
||||
.is_integer(true)
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.unit(" px")
|
||||
.on_update(move |number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyStroke {
|
||||
|
@ -808,6 +825,7 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutGroup {
|
|||
NumberInput::new(Some(stroke.line_join_miter_limit() as f64))
|
||||
.is_integer(true)
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.unit("")
|
||||
.on_update(move |number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyStroke {
|
||||
|
|
|
@ -37,6 +37,8 @@ const EXPOSED_BLEND_MODES: &[&[BlendMode]] = {
|
|||
]
|
||||
};
|
||||
|
||||
const BRUSH_MAX_SIZE: f64 = 5000.;
|
||||
|
||||
fn blend_mode_dropdown_idx(target_blend_mode: BlendMode) -> Option<u32> {
|
||||
let mut i = 0;
|
||||
for group in EXPOSED_BLEND_MODES {
|
||||
|
@ -145,6 +147,7 @@ impl LayoutHolder for BrushTool {
|
|||
NumberInput::new(Some(self.options.diameter))
|
||||
.label("Diameter")
|
||||
.min(1.)
|
||||
.max(BRUSH_MAX_SIZE) /* Anything bigger would cause the application to be unresponsive and eventually die */
|
||||
.unit(" px")
|
||||
.on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Diameter(number_input.value.unwrap())).into())
|
||||
.widget_holder(),
|
||||
|
@ -153,6 +156,7 @@ impl LayoutHolder for BrushTool {
|
|||
.label("Hardness")
|
||||
.min(0.)
|
||||
.max(100.)
|
||||
.mode_range()
|
||||
.unit("%")
|
||||
.on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Hardness(number_input.value.unwrap())).into())
|
||||
.widget_holder(),
|
||||
|
@ -161,6 +165,7 @@ impl LayoutHolder for BrushTool {
|
|||
.label("Flow")
|
||||
.min(1.)
|
||||
.max(100.)
|
||||
.mode_range()
|
||||
.unit("%")
|
||||
.on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Flow(number_input.value.unwrap())).into())
|
||||
.widget_holder(),
|
||||
|
@ -169,6 +174,7 @@ impl LayoutHolder for BrushTool {
|
|||
.label("Spacing")
|
||||
.min(1.)
|
||||
.max(100.)
|
||||
.mode_range()
|
||||
.unit("%")
|
||||
.on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Spacing(number_input.value.unwrap())).into())
|
||||
.widget_holder(),
|
||||
|
|
|
@ -87,6 +87,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
|||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
|||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(1.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
|
|
@ -89,6 +89,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
|||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| LineToolMessage::UpdateOptions(LineOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
|
|
@ -111,6 +111,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
|||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| PenToolMessage::UpdateOptions(PenOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
|
|
@ -118,6 +118,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
|||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| PolygonToolMessage::UpdateOptions(PolygonOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
|||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| RectangleToolMessage::UpdateOptions(RectangleOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
|||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(0.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
|
|
@ -122,6 +122,7 @@ fn create_text_widgets(tool: &TextTool) -> Vec<WidgetHolder> {
|
|||
.label("Size")
|
||||
.int()
|
||||
.min(1.)
|
||||
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| TextToolMessage::UpdateOptions(TextOptionsUpdate::FontSize(number_input.value.unwrap() as u32)).into())
|
||||
.widget_holder();
|
||||
vec![
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue