Project

General

Profile

Feature #22229

Updated by byroot (Jean Boussier) about 2 months ago

### Use case 

 `CGI.escapeHTML` has a fixed escape table: 

 ```c 
     HTML_ESCAPE('\'', "'"), 
     HTML_ESCAPE('&', "&"), 
     HTML_ESCAPE('"', """), 
     HTML_ESCAPE('<', "&lt;"), 
     HTML_ESCAPE('>', "&gt;"), 
 ``` 

 But in some context you may want to escape more or less characters than that, or escape them differently. 

 One example of this is Active Support JSON serialization, which by defaults escape `<>&` as    `\u003e\u003c\u0026`, to ensure that the generated 
 JSON can safely be interpolated inside a `<script>` tag without causing XSS vulnerabilities. 

 There's likely other use case as evidenced by the popularity of the `htmlentities` gem, which support several more escape tables. 

 ### Why not `gsub` ? 

 Today, this sort of escaping is performed using `gsub`, it works but is very noticeably slower than `CGI.escapeHTML` (see benchmarks on the PoC PR). 
 This is because the only way to use `gsub` with an escape table is to craft a regexp: 

 ```ruby 
 def escape(string, table) 
   pattern = Regexp.union(table.keys) 
   string.gsub(pattern, table) 
 end 

 puts escape("<script>", "<" => "&lt;", ">" => "&gt;") 
 ``` 

 If `gsub` could be used directly with the escape table it would certainly make it faster: 

 ```ruby 
 puts "<script>".gsub("<" => "&lt;", ">" => "&gt;") 
 ``` 

 But compared to `CGI.escapeHTML` it would still need to deal with noticeably more scenarios (multi character search, etc), so would always be slower than a dedicated escaping method. 

 `CGI.escapeHTML` can be more restrictive (single character search, etc). 

 ### Specification 

 ```ruby 
 GCI.escapeHTML("</script>", "<" => "&lt;", ">" => "&gt;") 
 ``` 

 - The escape table keys must be single characters (currently ASCII only, but could be muti-byte characters if deemed necessary). 

 ### Implementation 

 ``` 
 Pull Request: https://github.com/ruby/cgi/pull/55 (NB: it's at proof of concept / demo stage, if the feature is accepted I can polish it).

Back