Index: src/wp-includes/class-wp-html-comment-escape.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/wp-includes/class-wp-html-comment-escape.php	(date 1516817721000)
+++ src/wp-includes/class-wp-html-comment-escape.php	(date 1516817721000)
@@ -0,0 +1,165 @@
+<?php
+/**
+ * @package WordPress
+ * @subpackage Formatting
+ * @since x.x.x
+ */
+
+/**
+ * Core class used to escape contents of a HTML comment.
+ *
+ * @since x.x.x
+ */
+class WP_HTML_Comment_Escape {
+	/**
+	 * HTML_Comment constructor.
+	 *
+	 * @param string $text Text to use.
+	 */
+	public function __construct( $text ) {
+		$this->text = $text;
+	}
+
+	/**
+	 * Escapes the string for use in a HTML comment.
+	 *
+	 * Based upon the specs located at the following url
+	 * @url https://www.w3.org/TR/html51/syntax.html#sec-comments
+	 *
+	 * @return string Escaped string.
+	 */
+	public function escape() {
+		$safe_text = wp_check_invalid_utf8( $this->text );
+
+		do {
+			$changed = false;
+
+			while ( $this->unexpected_end_tag( $safe_text ) ) {
+				$safe_text = $this->strip_end_tag( $safe_text );
+				$changed = true;
+			}
+
+			while ( $this->invalid_starting_characters( $safe_text ) ) {
+				$safe_text = $this->strip_invalid_starting_characters( $safe_text );
+				$changed = true;
+			}
+
+			while ( $this->invalid_end_characters( $safe_text ) ) {
+				$safe_text = $this->strip_invalid_end_characters( $safe_text );
+				$changed = true;
+			}
+
+			while ( $this->invalid_characters( $safe_text ) ) {
+				$safe_text = $this->strip_invalid_characters( $safe_text );
+				$changed = true;
+			}
+		} while( $changed );
+
+		return apply_filters( 'esc_html_comment', $safe_text, $this->text );
+	}
+
+	/**
+	 * Detects if the text starts with invalid characters.
+	 *
+	 * Implements the following rules:
+	 * 1. must not start with a single U+003E GREATER-THAN SIGN character (>)
+	 * 2. nor start with a U+002D HYPHEN-MINUS character (-) followed by a U+003E GREATER-THAN SIGN (>) character
+	 *
+	 * @param string $text Text to parse.
+	 *
+	 * @return bool True if the text contains invalid characters.
+	 */
+	protected function invalid_starting_characters( $text ) {
+		return ( strpos( $text, '>' ) === 0  || strpos( $text, '->' ) === 0 );
+	}
+
+	/**
+	 * Detects if the text ends with invalid characters.
+	 *
+	 * Implements the rule: `not end with a U+002D HYPHEN-MINUS character (-).`
+	 *
+	 * @param string $text Text to parse.
+	 *
+	 * @return bool True if the text contains invalid ending characters.
+	 */
+	protected function invalid_end_characters( $text ) {
+		return ( substr( $text, -1 ) === '-' );
+	}
+
+	/**
+	 * Detects any unwanted ending sequences in the text.
+	 *
+	 * @param string $text Text to parse.
+	 *
+	 * @return bool True if an ending tag is found in the text.
+	 */
+	protected function unexpected_end_tag( $text ) {
+		return strpos( $text, '-->' ) !== false;
+	}
+
+	/**
+	 * Detects if the text contains invalid character sequences.
+	 *
+	 * Implements the rule: `nor contain two consecutive U+002D HYPHEN-MINUS characters (--)`
+	 *
+	 * @param string $text Text to parse.
+	 *
+	 * @return bool True if invalid characters exist in the text.
+	 */
+	protected function invalid_characters( $text ) {
+		return strpos( $text, '--' ) !== false;
+	}
+
+	/**
+	 * Strips invalid starting characters from the text.
+	 *
+	 * @param string $text Text to parse.
+	 *
+	 * @return string Replaced text.
+	 */
+	protected function strip_invalid_starting_characters( $text ) {
+		$text = preg_replace( '/^>/', '', $text );
+		$text = preg_replace( '/^->/', '', $text );
+
+		return ltrim( $text );
+	}
+
+	/**
+	 * Strips the comment end tag from the text.
+	 *
+	 * @param string $text Text to parse.
+	 *
+	 * @return string Replaced text.
+	 */
+	protected function strip_invalid_characters( $text ) {
+		$text = str_replace( array( ' --', '--' ), '', $text );
+
+		return trim( $text );
+	}
+
+	/**
+	 * Strips the comment end tag from the text.
+	 *
+	 * @param string $text Text to parse.
+	 *
+	 * @return string Replaced text.
+	 */
+	protected function strip_end_tag( $text ) {
+		$text = str_replace( array( ' -->', '--> ', '-->' ), '', $text );
+
+		return trim( $text );
+	}
+
+	/**
+	 * Strips invalid ending characters from the text.
+	 *
+	 * @param string $text Text to parse.
+	 *
+	 * @return string Replaced text.
+	 */
+	protected function strip_invalid_end_characters( $text ) {
+		$text = rtrim( $text, '-' );
+
+		return rtrim( $text );
+	}
+}
Index: src/wp-includes/formatting.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/wp-includes/formatting.php	(revision 974d3afb9c39101b61c48d99b8d1cec0410f282e)
+++ src/wp-includes/formatting.php	(date 1516719432000)
@@ -7,6 +7,8 @@
  * @package WordPress
  */
 
+require ABSPATH . WPINC . '/class-wp-html-comment-escape.php';
+
 /**
  * Replaces common plain text characters into formatted entities
  *
@@ -4230,6 +4232,20 @@
 	return apply_filters( 'esc_html', $safe_text, $text );
 }
 
+/**
+ * Escaping for HTML comments.
+ *
+ * @since x.x.x
+ *
+ * @param string $text Text to escape.
+ * @return string Escaped text.
+ */
+function esc_html_comment( $text ) {
+	$html_comment = new WP_HTML_Comment_Escape( $text );
+
+	return $html_comment->escape();
+}
+
 /**
  * Escaping for HTML attributes.
  *
Index: src/wp-includes/l10n.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/wp-includes/l10n.php	(revision 974d3afb9c39101b61c48d99b8d1cec0410f282e)
+++ src/wp-includes/l10n.php	(date 1516718473000)
@@ -235,6 +235,23 @@
 	return esc_html( translate( $text, $domain ) );
 }
 
+/**
+ * Retrieve the translation of $text and escapes it for safe use in a HTML comment.
+ *
+ * If there is no translation, or the text domain isn't loaded, the original text
+ * is escaped and returned..
+ *
+ * @since x.x.x
+ *
+ * @param string $text   Text to translate.
+ * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
+ *                       Default 'default'.
+ * @return string Translated text
+ */
+function esc_html_comment__( $text, $domain = 'default' ) {
+	return esc_html_comment( translate( $text, $domain ) );
+}
+
 /**
  * Display translated text.
  *
@@ -274,6 +291,34 @@
 	echo esc_html( translate( $text, $domain ) );
 }
 
+/**
+ * Display translated text that has been escaped for safe use in a HTML comment.
+ *
+ * @since x.x.x
+ *
+ * @param string $text   Text to translate.
+ * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
+ *                       Default 'default'.
+ */
+function esc_html_comment_e( $text, $domain = 'default' ) {
+	echo esc_html_comment( translate( $text, $domain ) );
+}
+
+/**
+ * Translate string with gettext context, and escapes it for safe use in a HTML comment.
+ *
+ * @since x.x.x
+ *
+ * @param string $text    Text to translate.
+ * @param string $context Context information for the translators.
+ * @param string $domain  Optional. Text domain. Unique identifier for retrieving translated strings.
+ *                        Default 'default'.
+ * @return string Translated text.
+ */
+function esc_html_comment_x( $text, $context, $domain = 'default' ) {
+	return esc_html_comment( translate_with_gettext_context( $text, $context, $domain ) );
+}
+
 /**
  * Retrieve translated string with gettext context.
  *
Index: tests/phpunit/tests/formatting/EscHtmlComment.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- tests/phpunit/tests/formatting/EscHtmlComment.php	(date 1516817721000)
+++ tests/phpunit/tests/formatting/EscHtmlComment.php	(date 1516817721000)
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * Class HTML_Comment
+ *
+ * @group esc_html_comment
+ */
+class Tests_Formatting_EscHtmlComment extends PHPUnit_Framework_TestCase {
+	/**
+	 * @dataProvider html_comment_data
+	 */
+	public function test_esc_html_comment( $input, $expected, $description = '' ) {
+		$this->assertEquals( $expected, esc_html_comment( $input ), $description );
+	}
+
+	/**
+	 * Data provider for the escape html comment
+	 *
+	 * @return array
+	 */
+	public function html_comment_data() {
+		return array(
+			array(
+				'<!-- data -->',
+				'<! data',
+				'Strip end comment tag'
+			),
+			array(
+				'<!-- data ---->>',
+				'<! data',
+				'Strip hidden end comment tag'
+			),
+			array(
+				'<!-- data --> more data',
+				'<! data more data',
+				'Strip end comment tag, preserving data after the tag'
+			),
+			array(
+				'<!-- data  -->  ',
+				'<! data',
+				'Strip end comment tag and removing spaces'
+			),
+			array(
+				'<!-- data  --> 1 ',
+				'<! data  1',
+				'Strip end comment tag maintaining spaces internally'
+			),
+			array(
+				'<!--<!--<!-- data -->',
+				'<!<!<! data',
+				'Strip end comment tag, not stripping starting tags'
+			),
+			array(
+				'-- data',
+				'data',
+				'Strip illegal prepending double dashes'
+			),
+			array(
+				'data -- more data',
+				'data more data',
+				'Strip illegal double dashes in content'
+			),
+			array(
+				'data --',
+				'data',
+				'Strip illegal double dashes at the end of the content'
+			),
+			array(
+				'data -',
+				'data',
+				'Strip illegal ending dash'
+			),
+			array(
+				'> data',
+				'data',
+				'Strip illegal starting greather-then-sign'
+			),
+			array(
+				'> data > more data',
+				'data > more data',
+				'Strip illegal starting greather-then-sign, keeping ones that are not the starting character'
+			),
+			array(
+				'data
+			 more data
+			 more data',
+				'data
+			 more data
+			 more data',
+				'Ensure new lines are untouched'
+			),
+			array(
+				'-- > test',
+				'test',
+				'Remove starting > after stripping other illegal characters'
+			),
+			array(
+				'test - -->-->',
+				'test',
+				'Remove end tags and dashes'
+			),
+			array(
+				'<html> this is not html </html>',
+				'<html> this is not html </html>',
+				'Ensure HTML characters are untouched'
+			),
+			array(
+				'It\'s a miracle',
+				'It\'s a miracle',
+				'Ensure quotes are untouched'
+			),
+		);
+	}
+}
