injectInvalidUTF8 inserts a raw invalid-UTF-8 byte sequence inside a JSON string value. Targets the parser's UTF-8 validation path: the parser must reject cleanly, never panic. Covers overlong encodings (0xC0 0xAF), truncated sequences (lone leading byte), never-valid bytes (0xFF / 0xFE), and a UTF-
(r *rand.Rand, data []byte)
| 802 | // sequences (lone leading byte), never-valid bytes (0xFF / 0xFE), and a UTF-8- |
| 803 | // encoded surrogate (which encoding/json rejects but some parsers accept). |
| 804 | func injectInvalidUTF8(r *rand.Rand, data []byte) []byte { |
| 805 | positions := stringInsertionPoints(data) |
| 806 | if len(positions) == 0 { |
| 807 | return data |
| 808 | } |
| 809 | pos := positions[r.Intn(len(positions))] |
| 810 | invalid := [][]byte{ |
| 811 | {0xC0, 0xAF}, // overlong '/' |
| 812 | {0xC1, 0xBF}, // overlong 2-byte |
| 813 | {0xE0, 0x80, 0xAF}, // overlong 3-byte |
| 814 | {0xF0, 0x80, 0x80, 0x80}, // overlong 4-byte |
| 815 | {0xE0}, // truncated 3-byte (lone leading byte) |
| 816 | {0xF0, 0x80}, // truncated 4-byte |
| 817 | {0xFF}, // never-valid byte |
| 818 | {0xFE}, // never-valid byte |
| 819 | {0xED, 0xA0, 0x80}, // UTF-8 encoding of U+D800 (lone surrogate) |
| 820 | } |
| 821 | seq := invalid[r.Intn(len(invalid))] |
| 822 | out := make([]byte, 0, len(data)+len(seq)) |
| 823 | out = append(out, data[:pos]...) |
| 824 | out = append(out, seq...) |
| 825 | out = append(out, data[pos:]...) |
| 826 | return out |
| 827 | } |
| 828 | |
| 829 | // injectLoneSurrogate corrupts a string by replacing a `\uXXXX` escape with a |
| 830 | // lone surrogate escape (\uD800 / \uDC00 alone, or a high-high pair). Targets |
nothing calls this directly
no test coverage detected