From 79a58a1902636edb2ed0b7d7378507caa3d4c9e5 Mon Sep 17 00:00:00 2001 From: Dennis Snell Date: Sat, 14 Oct 2023 18:34:55 -0700 Subject: [PATCH] HTML API: Guard against non-string attribute values. Because there are three ways for an attribute in HTML to exist, the HTML API reports three kinds of values for `get_attribute()` calls: - `null` means that no attribute exists of the given name - `true` means that the attribute exists but there is no value, e.g. ''. - a string value means that the attribute exists and has a value, e.g. ''. When operating on the value returned by `get_attribute()` then it's important to ensure that it's a string value before treating it as one. A call to `empty()` is not enough because a boolean attribute, being `true`, does not return `false` for `empty()`. In this patch blocks that read and then use attribute values as strings have been updated in order to guard against cases where the attribute might not be the string the code expects. --- lib/experimental/interactivity-api/directive-processing.php | 4 ++-- lib/experimental/interactivity-api/directives/wp-bind.php | 1 + lib/experimental/interactivity-api/directives/wp-class.php | 1 + lib/experimental/interactivity-api/directives/wp-context.php | 2 +- lib/experimental/interactivity-api/directives/wp-style.php | 2 ++ lib/experimental/interactivity-api/directives/wp-text.php | 2 +- packages/block-library/src/cover/index.php | 1 + 7 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/experimental/interactivity-api/directive-processing.php b/lib/experimental/interactivity-api/directive-processing.php index 41223c08158869..130b83f4e944bc 100644 --- a/lib/experimental/interactivity-api/directive-processing.php +++ b/lib/experimental/interactivity-api/directive-processing.php @@ -136,11 +136,11 @@ function gutenberg_interactivity_evaluate_reference( $path, array $context = arr ); /* - * Check first if the directive path is preceded by a negator operator (!), + * Check first if the directive path is preceded by a negation operator (!), * indicating that the value obtained from the Interactivity Store (or the * passed context) using the subsequent path should be negated. */ - $should_negate_value = '!' === $path[0]; + $should_negate_value = strlen( $path ) > 0 && '!' === $path[0]; $path = $should_negate_value ? substr( $path, 1 ) : $path; $path_segments = explode( '.', $path ); diff --git a/lib/experimental/interactivity-api/directives/wp-bind.php b/lib/experimental/interactivity-api/directives/wp-bind.php index 54be4a9faeb7d2..8192005bdbe321 100644 --- a/lib/experimental/interactivity-api/directives/wp-bind.php +++ b/lib/experimental/interactivity-api/directives/wp-bind.php @@ -26,6 +26,7 @@ function gutenberg_interactivity_process_wp_bind( $tags, $context ) { } $expr = $tags->get_attribute( $attr ); + $expr = is_string( $expr ) ? $expr : ''; $value = gutenberg_interactivity_evaluate_reference( $expr, $context->get_context() ); $tags->set_attribute( $bound_attr, $value ); } diff --git a/lib/experimental/interactivity-api/directives/wp-class.php b/lib/experimental/interactivity-api/directives/wp-class.php index 741cc75b42c60e..09c86d25dc1c98 100644 --- a/lib/experimental/interactivity-api/directives/wp-class.php +++ b/lib/experimental/interactivity-api/directives/wp-class.php @@ -26,6 +26,7 @@ function gutenberg_interactivity_process_wp_class( $tags, $context ) { } $expr = $tags->get_attribute( $attr ); + $expr = is_string( $expr ) ? $expr : ''; $add_class = gutenberg_interactivity_evaluate_reference( $expr, $context->get_context() ); if ( $add_class ) { $tags->add_class( $class_name ); diff --git a/lib/experimental/interactivity-api/directives/wp-context.php b/lib/experimental/interactivity-api/directives/wp-context.php index 5e3c5a140b2b0d..4151a9bf910008 100644 --- a/lib/experimental/interactivity-api/directives/wp-context.php +++ b/lib/experimental/interactivity-api/directives/wp-context.php @@ -18,7 +18,7 @@ function gutenberg_interactivity_process_wp_context( $tags, $context ) { } $value = $tags->get_attribute( 'data-wp-context' ); - if ( null === $value ) { + if ( ! is_string( $value ) || empty( $value ) ) { // No data-wp-context directive. return; } diff --git a/lib/experimental/interactivity-api/directives/wp-style.php b/lib/experimental/interactivity-api/directives/wp-style.php index 9c37f9082c2c0b..2072672b934082 100644 --- a/lib/experimental/interactivity-api/directives/wp-style.php +++ b/lib/experimental/interactivity-api/directives/wp-style.php @@ -26,9 +26,11 @@ function gutenberg_interactivity_process_wp_style( $tags, $context ) { } $expr = $tags->get_attribute( $attr ); + $expr = is_string( $expr ) ? $expr : ''; $style_value = gutenberg_interactivity_evaluate_reference( $expr, $context->get_context() ); if ( $style_value ) { $style_attr = $tags->get_attribute( 'style' ); + $style_attr = is_string( $style_value ) ? $style_attr : ''; $style_attr = gutenberg_interactivity_set_style( $style_attr, $style_name, $style_value ); $tags->set_attribute( 'style', $style_attr ); } else { diff --git a/lib/experimental/interactivity-api/directives/wp-text.php b/lib/experimental/interactivity-api/directives/wp-text.php index b0cfc98a74e702..185602a0da4016 100644 --- a/lib/experimental/interactivity-api/directives/wp-text.php +++ b/lib/experimental/interactivity-api/directives/wp-text.php @@ -18,7 +18,7 @@ function gutenberg_interactivity_process_wp_text( $tags, $context ) { } $value = $tags->get_attribute( 'data-wp-text' ); - if ( null === $value ) { + if ( ! is_string( $value ) || empty( $value ) ) { return; } diff --git a/packages/block-library/src/cover/index.php b/packages/block-library/src/cover/index.php index 5f6b2cadaaa570..5f7ab33bb1a0e9 100644 --- a/packages/block-library/src/cover/index.php +++ b/packages/block-library/src/cover/index.php @@ -54,6 +54,7 @@ function render_block_core_cover( $attributes, $content ) { $processor->next_tag(); $styles = $processor->get_attribute( 'style' ); + $styles = is_string( $styles ) ? $styles : ''; $merged_styles = ! empty( $styles ) ? $styles . ';' : ''; $merged_styles .= 'background-image:url(' . esc_url( $current_featured_image ) . ');';