зеркало из https://github.com/github/ruby.git
Revert "Optimize CGI.escapeHTML by reducing buffer extension"
This reverts commit 8d81e59aa7
.
`ALLOCA_N` does not check stack overflow unlike ALLOCV. I'll fix it and
re-commit it again.
This commit is contained in:
Родитель
804a7907a8
Коммит
71b14affc6
|
@ -1,40 +0,0 @@
|
||||||
prelude: require 'cgi/escape'
|
|
||||||
benchmark:
|
|
||||||
- name: escape_html_blank
|
|
||||||
prelude: str = ""
|
|
||||||
script: CGI.escapeHTML(str)
|
|
||||||
loop_count: 20000000
|
|
||||||
- name: escape_html_short_none
|
|
||||||
prelude: str = "abcde"
|
|
||||||
script: CGI.escapeHTML(str)
|
|
||||||
loop_count: 20000000
|
|
||||||
- name: escape_html_short_one
|
|
||||||
prelude: str = "abcd<"
|
|
||||||
script: CGI.escapeHTML(str)
|
|
||||||
loop_count: 20000000
|
|
||||||
- name: escape_html_short_all
|
|
||||||
prelude: str = "'&\"<>"
|
|
||||||
script: CGI.escapeHTML(str)
|
|
||||||
loop_count: 5000000
|
|
||||||
- name: escape_html_long_none
|
|
||||||
prelude: str = "abcde" * 300
|
|
||||||
script: CGI.escapeHTML(str)
|
|
||||||
loop_count: 1000000
|
|
||||||
- name: escape_html_long_all
|
|
||||||
prelude: str = "'&\"<>" * 10
|
|
||||||
script: CGI.escapeHTML(str)
|
|
||||||
loop_count: 1000000
|
|
||||||
- name: escape_html_real
|
|
||||||
prelude: | # http://example.com/
|
|
||||||
str = <<~HTML
|
|
||||||
<body>
|
|
||||||
<div>
|
|
||||||
<h1>Example Domain</h1>
|
|
||||||
<p>This domain is established to be used for illustrative examples in documents. You may use this
|
|
||||||
domain in examples without prior coordination or asking for permission.</p>
|
|
||||||
<p><a href="http://www.iana.org/domains/example">More information...</a></p>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
HTML
|
|
||||||
script: CGI.escapeHTML(str)
|
|
||||||
loop_count: 1000000
|
|
|
@ -11,20 +11,27 @@ RUBY_EXTERN const signed char ruby_digit36_to_number_table[];
|
||||||
static VALUE rb_cCGI, rb_mUtil, rb_mEscape;
|
static VALUE rb_cCGI, rb_mUtil, rb_mEscape;
|
||||||
static ID id_accept_charset;
|
static ID id_accept_charset;
|
||||||
|
|
||||||
#define HTML_ESCAPE_MAX_LEN 6
|
static void
|
||||||
|
html_escaped_cat(VALUE str, char c)
|
||||||
static const struct {
|
{
|
||||||
uint8_t len;
|
switch (c) {
|
||||||
char str[HTML_ESCAPE_MAX_LEN+1];
|
case '\'':
|
||||||
} html_escape_table[UCHAR_MAX+1] = {
|
rb_str_cat_cstr(str, "'");
|
||||||
#define HTML_ESCAPE(c, str) [c] = {rb_strlen_lit(str), str}
|
break;
|
||||||
HTML_ESCAPE('\'', "'"),
|
case '&':
|
||||||
HTML_ESCAPE('&', "&"),
|
rb_str_cat_cstr(str, "&");
|
||||||
HTML_ESCAPE('"', """),
|
break;
|
||||||
HTML_ESCAPE('<', "<"),
|
case '"':
|
||||||
HTML_ESCAPE('>', ">"),
|
rb_str_cat_cstr(str, """);
|
||||||
#undef HTML_ESCAPE
|
break;
|
||||||
};
|
case '<':
|
||||||
|
rb_str_cat_cstr(str, "<");
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
rb_str_cat_cstr(str, ">");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
preserve_original_state(VALUE orig, VALUE dest)
|
preserve_original_state(VALUE orig, VALUE dest)
|
||||||
|
@ -37,27 +44,36 @@ preserve_original_state(VALUE orig, VALUE dest)
|
||||||
static VALUE
|
static VALUE
|
||||||
optimized_escape_html(VALUE str)
|
optimized_escape_html(VALUE str)
|
||||||
{
|
{
|
||||||
const char *cstr = RSTRING_PTR(str);
|
long i, len, beg = 0;
|
||||||
const char *end = cstr + RSTRING_LEN(str);
|
VALUE dest = 0;
|
||||||
char *buf = ALLOCA_N(char, RSTRING_LEN(str) * HTML_ESCAPE_MAX_LEN);
|
const char *cstr;
|
||||||
|
|
||||||
char *dest = buf;
|
len = RSTRING_LEN(str);
|
||||||
while (cstr < end) {
|
cstr = RSTRING_PTR(str);
|
||||||
const unsigned char c = *cstr++;
|
|
||||||
uint8_t len = html_escape_table[c].len;
|
for (i = 0; i < len; i++) {
|
||||||
if (len) {
|
switch (cstr[i]) {
|
||||||
memcpy(dest, html_escape_table[c].str, len);
|
case '\'':
|
||||||
dest += len;
|
case '&':
|
||||||
}
|
case '"':
|
||||||
else {
|
case '<':
|
||||||
*dest++ = c;
|
case '>':
|
||||||
}
|
if (!dest) {
|
||||||
|
dest = rb_str_buf_new(len);
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_str_cat(dest, cstr + beg, i - beg);
|
||||||
|
beg = i + 1;
|
||||||
|
|
||||||
|
html_escaped_cat(dest, cstr[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RSTRING_LEN(str) < (dest - buf)) {
|
if (dest) {
|
||||||
VALUE escaped = rb_str_new(buf, dest - buf);
|
rb_str_cat(dest, cstr + beg, len - beg);
|
||||||
preserve_original_state(str, escaped);
|
preserve_original_state(str, dest);
|
||||||
return escaped;
|
return dest;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return rb_str_dup(str);
|
return rb_str_dup(str);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче