From fd338c945f54ec6face54880a586124d312d4226 Mon Sep 17 00:00:00 2001 From: Omar Magdy <99906646+omagdy7@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:31:28 +0300 Subject: [PATCH] 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 --- .../export_dialog_message_handler.rs | 1 + .../new_document_dialog_message_handler.rs | 2 ++ .../preferences_dialog_message_handler.rs | 1 + .../messages/layout/layout_message_handler.rs | 2 +- .../utility_types/widgets/input_widgets.rs | 3 +-- .../node_properties.rs | 10 +++++++++- .../properties_panel/utility_functions.rs | 18 ++++++++++++++++++ .../messages/tool/tool_messages/brush_tool.rs | 6 ++++++ .../tool/tool_messages/ellipse_tool.rs | 1 + .../tool/tool_messages/freehand_tool.rs | 1 + .../messages/tool/tool_messages/line_tool.rs | 1 + .../messages/tool/tool_messages/pen_tool.rs | 1 + .../tool/tool_messages/polygon_tool.rs | 1 + .../tool/tool_messages/rectangle_tool.rs | 1 + .../messages/tool/tool_messages/spline_tool.rs | 1 + .../messages/tool/tool_messages/text_tool.rs | 1 + 16 files changed, 47 insertions(+), 4 deletions(-) diff --git a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs index c09bb4ce..23e48c29 100644 --- a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs +++ b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs @@ -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(), diff --git a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs index 1ca85ed1..f69d0b3a 100644 --- a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs +++ b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs @@ -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) diff --git a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs index bb571795..102ddc2e 100644 --- a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs +++ b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs @@ -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(), diff --git a/editor/src/messages/layout/layout_message_handler.rs b/editor/src/messages/layout/layout_message_handler.rs index 258d1954..8b3d1fc2 100644 --- a/editor/src/messages/layout/layout_message_handler.rs +++ b/editor/src/messages/layout/layout_message_handler.rs @@ -183,7 +183,7 @@ impl Vec> MessageHandler 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"); diff --git a/editor/src/messages/layout/utility_types/widgets/input_widgets.rs b/editor/src/messages/layout/utility_types/widgets/input_widgets.rs index 474bb879..6e19704d 100644 --- a/editor/src/messages/layout/utility_types/widgets/input_widgets.rs +++ b/editor/src/messages/layout/utility_types/widgets/input_widgets.rs @@ -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) } } diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs index 0a7bcd8c..662acfdd 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs @@ -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 { 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); diff --git a/editor/src/messages/portfolio/document/properties_panel/utility_functions.rs b/editor/src/messages/portfolio/document/properties_panel/utility_functions.rs index 7ef3d669..86d16bd3 100644 --- a/editor/src/messages/portfolio/document/properties_panel/utility_functions.rs +++ b/editor/src/messages/portfolio/document/properties_panel/utility_functions.rs @@ -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 { diff --git a/editor/src/messages/tool/tool_messages/brush_tool.rs b/editor/src/messages/tool/tool_messages/brush_tool.rs index cc01fe23..c013f231 100644 --- a/editor/src/messages/tool/tool_messages/brush_tool.rs +++ b/editor/src/messages/tool/tool_messages/brush_tool.rs @@ -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 { 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(), diff --git a/editor/src/messages/tool/tool_messages/ellipse_tool.rs b/editor/src/messages/tool/tool_messages/ellipse_tool.rs index 1418c3dd..826d8ea2 100644 --- a/editor/src/messages/tool/tool_messages/ellipse_tool.rs +++ b/editor/src/messages/tool/tool_messages/ellipse_tool.rs @@ -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() } diff --git a/editor/src/messages/tool/tool_messages/freehand_tool.rs b/editor/src/messages/tool/tool_messages/freehand_tool.rs index d58dd64a..0c5475b5 100644 --- a/editor/src/messages/tool/tool_messages/freehand_tool.rs +++ b/editor/src/messages/tool/tool_messages/freehand_tool.rs @@ -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() } diff --git a/editor/src/messages/tool/tool_messages/line_tool.rs b/editor/src/messages/tool/tool_messages/line_tool.rs index 340800c8..dbf1249e 100644 --- a/editor/src/messages/tool/tool_messages/line_tool.rs +++ b/editor/src/messages/tool/tool_messages/line_tool.rs @@ -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() } diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs index 8a68d0d1..d4d05424 100644 --- a/editor/src/messages/tool/tool_messages/pen_tool.rs +++ b/editor/src/messages/tool/tool_messages/pen_tool.rs @@ -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() } diff --git a/editor/src/messages/tool/tool_messages/polygon_tool.rs b/editor/src/messages/tool/tool_messages/polygon_tool.rs index 3abbe6f2..f7cbe911 100644 --- a/editor/src/messages/tool/tool_messages/polygon_tool.rs +++ b/editor/src/messages/tool/tool_messages/polygon_tool.rs @@ -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() } diff --git a/editor/src/messages/tool/tool_messages/rectangle_tool.rs b/editor/src/messages/tool/tool_messages/rectangle_tool.rs index 65286f61..3239d6a2 100644 --- a/editor/src/messages/tool/tool_messages/rectangle_tool.rs +++ b/editor/src/messages/tool/tool_messages/rectangle_tool.rs @@ -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() } diff --git a/editor/src/messages/tool/tool_messages/spline_tool.rs b/editor/src/messages/tool/tool_messages/spline_tool.rs index 22c2f491..3eff6875 100644 --- a/editor/src/messages/tool/tool_messages/spline_tool.rs +++ b/editor/src/messages/tool/tool_messages/spline_tool.rs @@ -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() } diff --git a/editor/src/messages/tool/tool_messages/text_tool.rs b/editor/src/messages/tool/tool_messages/text_tool.rs index b32bac9e..76c52de6 100644 --- a/editor/src/messages/tool/tool_messages/text_tool.rs +++ b/editor/src/messages/tool/tool_messages/text_tool.rs @@ -122,6 +122,7 @@ fn create_text_widgets(tool: &TextTool) -> Vec { .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![