From a486c86eee761467f3047be0155f65b03e1e99d4 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Fri, 29 Nov 2024 16:04:35 +0000 Subject: [PATCH] LibWeb: Limit `HTMLCanvasElement` width and height to allowed values Setting the `width` or `height` properties of `HTMLCanvasElement` to a value greater than 2147483647 will now cause the property to be set to its default value. --- Libraries/LibWeb/HTML/HTMLCanvasElement.cpp | 32 ++++++++++++--- Libraries/LibWeb/HTML/HTMLCanvasElement.h | 9 +++-- .../HTML/unsigned-long-reflection.txt | 40 +++++++++++++++++++ .../input/HTML/unsigned-long-reflection.html | 2 + 4 files changed, 73 insertions(+), 10 deletions(-) diff --git a/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp b/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp index 47f70665dda..f5bcb806a08 100644 --- a/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp @@ -82,22 +82,36 @@ void HTMLCanvasElement::apply_presentational_hints(CSS::StyleProperties& style) CSS::StyleValueList::Separator::Space)); } -unsigned HTMLCanvasElement::width() const +// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-width +WebIDL::UnsignedLong HTMLCanvasElement::width() const { + // The width and height IDL attributes must reflect the respective content attributes of the same name, with the same defaults. // https://html.spec.whatwg.org/multipage/canvas.html#obtain-numeric-values // The rules for parsing non-negative integers must be used to obtain their numeric values. // If an attribute is missing, or if parsing its value returns an error, then the default value must be used instead. // The width attribute defaults to 300 - return parse_non_negative_integer(get_attribute_value(HTML::AttributeNames::width)).value_or(300); + if (auto width_string = get_attribute(HTML::AttributeNames::width); width_string.has_value()) { + if (auto width = parse_non_negative_integer(*width_string); width.has_value() && *width <= 2147483647) + return *width; + } + + return 300; } -unsigned HTMLCanvasElement::height() const +// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-height +WebIDL::UnsignedLong HTMLCanvasElement::height() const { + // The width and height IDL attributes must reflect the respective content attributes of the same name, with the same defaults. // https://html.spec.whatwg.org/multipage/canvas.html#obtain-numeric-values // The rules for parsing non-negative integers must be used to obtain their numeric values. // If an attribute is missing, or if parsing its value returns an error, then the default value must be used instead. // the height attribute defaults to 150 - return parse_non_negative_integer(get_attribute_value(HTML::AttributeNames::height)).value_or(150); + if (auto height_string = get_attribute(HTML::AttributeNames::height); height_string.has_value()) { + if (auto height = parse_non_negative_integer(*height_string); height.has_value() && *height <= 2147483647) + return *height; + } + + return 150; } void HTMLCanvasElement::reset_context_to_default_state() @@ -114,16 +128,22 @@ void HTMLCanvasElement::reset_context_to_default_state() }); } -WebIDL::ExceptionOr HTMLCanvasElement::set_width(unsigned value) +WebIDL::ExceptionOr HTMLCanvasElement::set_width(WebIDL::UnsignedLong value) { + if (value > 2147483647) + value = 300; + TRY(set_attribute(HTML::AttributeNames::width, String::number(value))); m_surface = nullptr; reset_context_to_default_state(); return {}; } -WebIDL::ExceptionOr HTMLCanvasElement::set_height(unsigned value) +WebIDL::ExceptionOr HTMLCanvasElement::set_height(WebIDL::UnsignedLong value) { + if (value > 2147483647) + value = 150; + TRY(set_attribute(HTML::AttributeNames::height, String::number(value))); m_surface = nullptr; reset_context_to_default_state(); diff --git a/Libraries/LibWeb/HTML/HTMLCanvasElement.h b/Libraries/LibWeb/HTML/HTMLCanvasElement.h index 3cc4d21fef0..730aff74769 100644 --- a/Libraries/LibWeb/HTML/HTMLCanvasElement.h +++ b/Libraries/LibWeb/HTML/HTMLCanvasElement.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace Web::HTML { @@ -29,11 +30,11 @@ public: JS::ThrowCompletionOr get_context(String const& type, JS::Value options); - unsigned width() const; - unsigned height() const; + WebIDL::UnsignedLong width() const; + WebIDL::UnsignedLong height() const; - WebIDL::ExceptionOr set_width(unsigned); - WebIDL::ExceptionOr set_height(unsigned); + WebIDL::ExceptionOr set_width(WebIDL::UnsignedLong); + WebIDL::ExceptionOr set_height(WebIDL::UnsignedLong); String to_data_url(StringView type, JS::Value quality); WebIDL::ExceptionOr to_blob(GC::Ref callback, StringView type, JS::Value quality); diff --git a/Tests/LibWeb/Text/expected/HTML/unsigned-long-reflection.txt b/Tests/LibWeb/Text/expected/HTML/unsigned-long-reflection.txt index 7bba47b9a3d..f2e86e00ad5 100644 --- a/Tests/LibWeb/Text/expected/HTML/unsigned-long-reflection.txt +++ b/Tests/LibWeb/Text/expected/HTML/unsigned-long-reflection.txt @@ -1,3 +1,43 @@ +canvas.getAttribute("width") after canvas.setAttribute("width", "0"): 0 +canvas.width after canvas.setAttribute("width", "0"): 0 +canvas.getAttribute("width") after canvas.width = 0: 0 +canvas.width after canvas.width = 0: 0 +canvas.getAttribute("width") after canvas.setAttribute("width", "1"): 1 +canvas.width after canvas.setAttribute("width", "1"): 1 +canvas.getAttribute("width") after canvas.width = 1: 1 +canvas.width after canvas.width = 1: 1 +canvas.getAttribute("width") after canvas.setAttribute("width", "2147483647"): 2147483647 +canvas.width after canvas.setAttribute("width", "2147483647"): 2147483647 +canvas.getAttribute("width") after canvas.width = 2147483647: 2147483647 +canvas.width after canvas.width = 2147483647: 2147483647 +canvas.getAttribute("width") after canvas.setAttribute("width", "2147483648"): 2147483648 +canvas.width after canvas.setAttribute("width", "2147483648"): 300 +canvas.getAttribute("width") after canvas.width = 2147483648: 300 +canvas.width after canvas.width = 2147483648: 300 +canvas.getAttribute("width") after canvas.setAttribute("width", "4294967295"): 4294967295 +canvas.width after canvas.setAttribute("width", "4294967295"): 300 +canvas.getAttribute("width") after canvas.width = 4294967295: 300 +canvas.width after canvas.width = 4294967295: 300 +canvas.getAttribute("height") after canvas.setAttribute("height", "0"): 0 +canvas.height after canvas.setAttribute("height", "0"): 0 +canvas.getAttribute("height") after canvas.height = 0: 0 +canvas.height after canvas.height = 0: 0 +canvas.getAttribute("height") after canvas.setAttribute("height", "1"): 1 +canvas.height after canvas.setAttribute("height", "1"): 1 +canvas.getAttribute("height") after canvas.height = 1: 1 +canvas.height after canvas.height = 1: 1 +canvas.getAttribute("height") after canvas.setAttribute("height", "2147483647"): 2147483647 +canvas.height after canvas.setAttribute("height", "2147483647"): 2147483647 +canvas.getAttribute("height") after canvas.height = 2147483647: 2147483647 +canvas.height after canvas.height = 2147483647: 2147483647 +canvas.getAttribute("height") after canvas.setAttribute("height", "2147483648"): 2147483648 +canvas.height after canvas.setAttribute("height", "2147483648"): 150 +canvas.getAttribute("height") after canvas.height = 2147483648: 150 +canvas.height after canvas.height = 2147483648: 150 +canvas.getAttribute("height") after canvas.setAttribute("height", "4294967295"): 4294967295 +canvas.height after canvas.setAttribute("height", "4294967295"): 150 +canvas.getAttribute("height") after canvas.height = 4294967295: 150 +canvas.height after canvas.height = 4294967295: 150 img.getAttribute("height") after img.setAttribute("height", "0"): 0 img.height after img.setAttribute("height", "0"): 0 img.getAttribute("height") after img.height = 0: 0 diff --git a/Tests/LibWeb/Text/input/HTML/unsigned-long-reflection.html b/Tests/LibWeb/Text/input/HTML/unsigned-long-reflection.html index e596843562c..4dc4f87f3fd 100644 --- a/Tests/LibWeb/Text/input/HTML/unsigned-long-reflection.html +++ b/Tests/LibWeb/Text/input/HTML/unsigned-long-reflection.html @@ -42,6 +42,8 @@ return input; } + testProperty("canvas", "width", (canvas) => canvas.width, (canvas, value) => canvas.width = value); + testProperty("canvas", "height", (canvas) => canvas.height, (canvas, value) => canvas.height = value); testProperty("img", "height", (img) => img.height, (img, value) => img.height = value); testProperty("img", "hspace", (img) => img.hspace, (img, value) => img.hspace = value); testProperty("img", "width", (img) => img.width, (img, value) => img.width = value);