/src/cmark/src/houdini_html_e.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include <assert.h> |
2 | | #include <stdio.h> |
3 | | #include <string.h> |
4 | | |
5 | | #include "houdini.h" |
6 | | |
7 | | #if !defined(__has_builtin) |
8 | | # define __has_builtin(b) 0 |
9 | | #endif |
10 | | |
11 | | #if !__has_builtin(__builtin_expect) |
12 | | # define __builtin_expect(e, v) (e) |
13 | | #endif |
14 | | |
15 | | #define likely(e) __builtin_expect((e), 1) |
16 | 24.4M | #define unlikely(e) __builtin_expect((e), 0) |
17 | | |
18 | | /** |
19 | | * According to the OWASP rules: |
20 | | * |
21 | | * & --> & |
22 | | * < --> < |
23 | | * > --> > |
24 | | * " --> " |
25 | | * ' --> ' ' is not recommended |
26 | | * / --> / forward slash is included as it helps end an HTML entity |
27 | | * |
28 | | */ |
29 | | static const char HTML_ESCAPE_TABLE[] = { |
30 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
31 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4, |
32 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
33 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
34 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
35 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
36 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
37 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
38 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
39 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
40 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
41 | | }; |
42 | | |
43 | | static const char *HTML_ESCAPES[] = {"", """, "&", "'", |
44 | | "/", "<", ">"}; |
45 | | |
46 | | int houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src, bufsize_t size, |
47 | 9.62M | int secure) { |
48 | 9.62M | bufsize_t i = 0, org, esc = 0; |
49 | | |
50 | 25.0M | while (i < size) { |
51 | 24.4M | org = i; |
52 | 559M | while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0) |
53 | 535M | i++; |
54 | | |
55 | 24.4M | if (i > org) |
56 | 18.1M | cmark_strbuf_put(ob, src + org, i - org); |
57 | | |
58 | | /* escaping */ |
59 | 24.4M | if (unlikely(i >= size)) |
60 | 8.94M | break; |
61 | | |
62 | | /* The forward slash is only escaped in secure mode */ |
63 | 15.4M | if ((src[i] == '/' || src[i] == '\'') && !secure) { |
64 | 2.63M | cmark_strbuf_putc(ob, src[i]); |
65 | 12.8M | } else { |
66 | 12.8M | cmark_strbuf_puts(ob, HTML_ESCAPES[esc]); |
67 | 12.8M | } |
68 | | |
69 | 15.4M | i++; |
70 | 15.4M | } |
71 | | |
72 | 9.62M | return 1; |
73 | 9.62M | } |
74 | | |
75 | 0 | int houdini_escape_html(cmark_strbuf *ob, const uint8_t *src, bufsize_t size) { |
76 | 0 | return houdini_escape_html0(ob, src, size, 1); |
77 | 0 | } |