Repository navigation
Commit 2643d11
authored
Decode inbound lone-surrogate frames instead of dropping them (#77)
Parse decoded the quoted Data of inbound Input/Click/ContextMenu/Remove frames
with strconv.Unquote, returning failure when it errored. The browser encodes that
data with JSON.stringify, whose grammar is not a subset of strconv.Unquote's: a
lone UTF-16 surrogate is emitted as the literal escape "\udXXX" (JSON.stringify
does not throw on lone surrogates), which strconv.Unquote rejects. ReadLoop then
silently discarded the whole frame, before the ToValidUTF8 sanitizer ran, losing a
legitimate user event. Input values are UTF-16 DOMStrings and can hold lone
surrogates (emoji split, IME/paste, programmatic set).
Fall back to a JSON string decode (which maps a lone surrogate to U+FFFD) when
strconv.Unquote fails, so the event is delivered sanitized rather than dropped. The
message is rejected only if both decoders fail; the common and verbatim paths are
unchanged.
The fallback was chosen by benchmarking three decoders (strconv.Unquote only, JSON
only, and Unquote-with-JSON-fallback): pure JSON regressed every inbound frame ~10x
with 4-5 extra allocations, while the fallback matches strconv.Unquote on the common
path and pays the JSON cost only on the rare surrogate case. The benchmark also
exposed that inlining json.Unmarshal(&data) forced Parse's data local to escape to
the heap on every call (a uniform +1 alloc on all frames, including the unquoted and
Set/Call paths that never decode); moving the address-taken target into
jsonUnquoteString keeps data on the stack. BenchmarkParse confirms the common,
unquoted and verbatim paths are allocation-identical to before; only the
previously-dropped surrogate frame costs more. Kept as a regression guard.1 parent 40b9c2c commit 2643d11
3 files changed
Lines changed: 86 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
| |||
109 | 110 | | |
110 | 111 | | |
111 | 112 | | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
117 | 120 | | |
118 | 121 | | |
119 | 122 | | |
| |||
125 | 128 | | |
126 | 129 | | |
127 | 130 | | |
128 | | - | |
129 | | - | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
130 | 146 | | |
131 | 147 | | |
132 | 148 | | |
| |||
143 | 159 | | |
144 | 160 | | |
145 | 161 | | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
146 | 171 | | |
147 | 172 | | |
148 | 173 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
170 | 170 | | |
171 | 171 | | |
172 | 172 | | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
173 | 196 | | |
174 | 197 | | |
175 | 198 | | |
| |||
0 commit comments