injectLoneSurrogate corrupts a string by replacing a `\uXXXX` escape with a lone surrogate escape (\uD800 / \uDC00 alone, or a high-high pair). Targets the escape decoder's surrogate-combination path: it must refuse to combine these into a valid code point and must reject the string cleanly. If no `
(r *rand.Rand, data []byte)
| 833 | // `\u` escape exists in data, the operator inserts a lone surrogate escape at |
| 834 | // a random string-body position instead. |
| 835 | func injectLoneSurrogate(r *rand.Rand, data []byte) []byte { |
| 836 | // Find existing \u escapes. |
| 837 | var escPos []int |
| 838 | for i := 0; i+1 < len(data); i++ { |
| 839 | if data[i] == '\\' && data[i+1] == 'u' { |
| 840 | escPos = append(escPos, i) |
| 841 | } |
| 842 | } |
| 843 | if len(escPos) > 0 { |
| 844 | pos := escPos[r.Intn(len(escPos))] |
| 845 | end := pos + 6 |
| 846 | if end > len(data) { |
| 847 | end = len(data) |
| 848 | } |
| 849 | var seq []byte |
| 850 | switch r.Intn(3) { |
| 851 | case 0: |
| 852 | seq = []byte(`\uD800`) // high alone |
| 853 | case 1: |
| 854 | seq = []byte(`\uDC00`) // low alone |
| 855 | default: |
| 856 | seq = []byte(`\uD800\uD800`) // two highs |
| 857 | } |
| 858 | out := make([]byte, 0, len(data)-6+len(seq)) |
| 859 | out = append(out, data[:pos]...) |
| 860 | out = append(out, seq...) |
| 861 | out = append(out, data[end:]...) |
| 862 | return out |
| 863 | } |
| 864 | // Fallback: insert a lone-surrogate escape inside a string body. |
| 865 | positions := stringInsertionPoints(data) |
| 866 | if len(positions) == 0 { |
| 867 | return data |
| 868 | } |
| 869 | pos := positions[r.Intn(len(positions))] |
| 870 | seq := []byte(`\uD800`) |
| 871 | out := make([]byte, 0, len(data)+len(seq)) |
| 872 | out = append(out, data[:pos]...) |
| 873 | out = append(out, seq...) |
| 874 | out = append(out, data[pos:]...) |
| 875 | return out |
| 876 | } |
| 877 | |
| 878 | // injectUnbalancedOpen inserts unmatched '{' or '[' opens at a random |
| 879 | // position. This produces structures the grammar generator CANNOT emit: |
nothing calls this directly
no test coverage detected