Download this file
| 1 | package launchctx |
| 2 | |
| 3 | import "strconv" |
| 4 | |
| 5 | // encoding/json replaces unpaired UTF-16 escapes with U+FFFD. Refuse that |
| 6 | // lossy conversion before decoding identities and paths. |
| 7 | func validSurrogates(raw []byte) bool { |
| 8 | quoted := false |
| 9 | for i := 0; i < len(raw); i++ { |
| 10 | if raw[i] == '"' { |
| 11 | quoted = !quoted |
| 12 | continue |
| 13 | } |
| 14 | if !quoted || raw[i] != '\\' { |
| 15 | continue |
| 16 | } |
| 17 | i++ |
| 18 | if i >= len(raw) { |
| 19 | return false |
| 20 | } |
| 21 | if raw[i] != 'u' { |
| 22 | continue |
| 23 | } |
| 24 | if i+4 >= len(raw) { |
| 25 | return false |
| 26 | } |
| 27 | n, err := strconv.ParseUint(string(raw[i+1:i+5]), 16, 16) |
| 28 | if err != nil { |
| 29 | return false |
| 30 | } |
| 31 | i += 4 |
| 32 | if n >= 0xdc00 && n <= 0xdfff { |
| 33 | return false |
| 34 | } |
| 35 | if n < 0xd800 || n > 0xdbff { |
| 36 | continue |
| 37 | } |
| 38 | if i+6 >= len(raw) || raw[i+1] != '\\' || raw[i+2] != 'u' { |
| 39 | return false |
| 40 | } |
| 41 | low, err := strconv.ParseUint(string(raw[i+3:i+7]), 16, 16) |
| 42 | if err != nil || low < 0xdc00 || low > 0xdfff { |
| 43 | return false |
| 44 | } |
| 45 | i += 6 |
| 46 | } |
| 47 | return true |
| 48 | } |
| 49 | |