NOTE: keep in sync with stringBytes below.
(s string, escapeHTML bool)
| 886 | |
| 887 | // NOTE: keep in sync with stringBytes below. |
| 888 | func (e *encodeState) string(s string, escapeHTML bool) { |
| 889 | e.WriteByte('"') |
| 890 | start := 0 |
| 891 | for i := 0; i < len(s); { |
| 892 | if b := s[i]; b < utf8.RuneSelf { |
| 893 | if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) { |
| 894 | i++ |
| 895 | continue |
| 896 | } |
| 897 | if start < i { |
| 898 | e.WriteString(s[start:i]) |
| 899 | } |
| 900 | e.WriteByte('\\') |
| 901 | switch b { |
| 902 | case '\\', '"': |
| 903 | e.WriteByte(b) |
| 904 | case '\n': |
| 905 | e.WriteByte('n') |
| 906 | case '\r': |
| 907 | e.WriteByte('r') |
| 908 | case '\t': |
| 909 | e.WriteByte('t') |
| 910 | default: |
| 911 | // This encodes bytes < 0x20 except for \t, \n and \r. |
| 912 | // If escapeHTML is set, it also escapes <, >, and & |
| 913 | // because they can lead to security holes when |
| 914 | // user-controlled strings are rendered into JSON |
| 915 | // and served to some browsers. |
| 916 | e.WriteString(`u00`) |
| 917 | e.WriteByte(hex[b>>4]) |
| 918 | e.WriteByte(hex[b&0xF]) |
| 919 | } |
| 920 | i++ |
| 921 | start = i |
| 922 | continue |
| 923 | } |
| 924 | c, size := utf8.DecodeRuneInString(s[i:]) |
| 925 | if c == utf8.RuneError && size == 1 { |
| 926 | if start < i { |
| 927 | e.WriteString(s[start:i]) |
| 928 | } |
| 929 | e.WriteString(`\ufffd`) |
| 930 | i += size |
| 931 | start = i |
| 932 | continue |
| 933 | } |
| 934 | // U+2028 is LINE SEPARATOR. |
| 935 | // U+2029 is PARAGRAPH SEPARATOR. |
| 936 | // They are both technically valid characters in JSON strings, |
| 937 | // but don't work in JSONP, which has to be evaluated as JavaScript, |
| 938 | // and can lead to security holes there. It is valid JSON to |
| 939 | // escape them, so we do so unconditionally. |
| 940 | // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. |
| 941 | if c == '\u2028' || c == '\u2029' { |
| 942 | if start < i { |
| 943 | e.WriteString(s[start:i]) |
| 944 | } |
| 945 | e.WriteString(`\u202`) |
no outgoing calls
no test coverage detected