Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions ext/standard/html.c
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,12 @@ static inline size_t write_octet_sequence(unsigned char *buf, enum entity_charse
}
}

/* [0-9A-Za-z], independent of the locale */
static zend_always_inline bool is_entity_name_byte(unsigned char c)
{
return (unsigned char)((c | 0x20) - 'a') < 26 || (unsigned char)(c - '0') < 10;
}

/* {{{ traverse_for_entities
* Auxiliary function to php_unescape_html_entities().
* - The argument "all" determines if all numeric entities are decode or only those
Expand All @@ -820,7 +826,8 @@ static void traverse_for_entities(
const int doctype = flags & ENT_HTML_DOC_TYPE_MASK;

while (current_ptr < input_end) {
const char *ampersand_ptr = memchr(current_ptr, '&', input_end - current_ptr);
/* Runs of '&' would call memchr() for every byte */
const char *ampersand_ptr = *current_ptr == '&' ? current_ptr : memchr(current_ptr, '&', input_end - current_ptr);
if (!ampersand_ptr) {
const size_t tail_len = input_end - current_ptr;
if (tail_len > 0) {
Expand Down Expand Up @@ -874,10 +881,13 @@ static void traverse_for_entities(
} else {
/* Processing named entity */
const char *name_start = current_ptr + 1;
/* Search for ';' */
const size_t max_search_len = MIN(LONGEST_ENTITY_LENGTH + 1, input_end - name_start);
const char *semi_colon_ptr = memchr(name_start, ';', max_search_len);
if (!semi_colon_ptr) {
const char *semi_colon_ptr = name_start;
const char *const name_limit = name_start + MIN(LONGEST_ENTITY_LENGTH, input_end - name_start - 1);
/* A name is letters and digits only, so the first other byte must be the ';' */
while (semi_colon_ptr < name_limit && is_entity_name_byte(*semi_colon_ptr)) {
semi_colon_ptr++;
}
if (*semi_colon_ptr != ';') {
goto invalid_incomplete_entity;
} else {
const size_t name_len = semi_colon_ptr - name_start;
Expand Down
Loading