@@ -18,6 +18,12 @@ type Query struct {
1818 Parts []Part
1919}
2020
21+ // utf.DecodeRune returns the utf8.RuneError for errors. But that is actually rune U+FFFD -- the unicode replacement
22+ // character. utf8.RuneError is not an error if it is also width 3.
23+ //
24+ // https://github.com/jackc/pgx/issues/1380
25+ const replacementcharacterwidth = 3
26+
2127func (q * Query ) Sanitize (args ... interface {}) (string , error ) {
2228 argUse := make ([]bool , len (args ))
2329 buf := & bytes.Buffer {}
@@ -138,11 +144,13 @@ func rawState(l *sqlLexer) stateFn {
138144 return multilineCommentState
139145 }
140146 case utf8 .RuneError :
141- if l .pos - l .start > 0 {
142- l .parts = append (l .parts , l .src [l .start :l .pos ])
143- l .start = l .pos
147+ if width != replacementcharacterwidth {
148+ if l .pos - l .start > 0 {
149+ l .parts = append (l .parts , l .src [l .start :l .pos ])
150+ l .start = l .pos
151+ }
152+ return nil
144153 }
145- return nil
146154 }
147155 }
148156}
@@ -160,11 +168,13 @@ func singleQuoteState(l *sqlLexer) stateFn {
160168 }
161169 l .pos += width
162170 case utf8 .RuneError :
163- if l .pos - l .start > 0 {
164- l .parts = append (l .parts , l .src [l .start :l .pos ])
165- l .start = l .pos
171+ if width != replacementcharacterwidth {
172+ if l .pos - l .start > 0 {
173+ l .parts = append (l .parts , l .src [l .start :l .pos ])
174+ l .start = l .pos
175+ }
176+ return nil
166177 }
167- return nil
168178 }
169179 }
170180}
@@ -182,11 +192,13 @@ func doubleQuoteState(l *sqlLexer) stateFn {
182192 }
183193 l .pos += width
184194 case utf8 .RuneError :
185- if l .pos - l .start > 0 {
186- l .parts = append (l .parts , l .src [l .start :l .pos ])
187- l .start = l .pos
195+ if width != replacementcharacterwidth {
196+ if l .pos - l .start > 0 {
197+ l .parts = append (l .parts , l .src [l .start :l .pos ])
198+ l .start = l .pos
199+ }
200+ return nil
188201 }
189- return nil
190202 }
191203 }
192204}
@@ -228,11 +240,13 @@ func escapeStringState(l *sqlLexer) stateFn {
228240 }
229241 l .pos += width
230242 case utf8 .RuneError :
231- if l .pos - l .start > 0 {
232- l .parts = append (l .parts , l .src [l .start :l .pos ])
233- l .start = l .pos
243+ if width != replacementcharacterwidth {
244+ if l .pos - l .start > 0 {
245+ l .parts = append (l .parts , l .src [l .start :l .pos ])
246+ l .start = l .pos
247+ }
248+ return nil
234249 }
235- return nil
236250 }
237251 }
238252}
@@ -249,11 +263,13 @@ func oneLineCommentState(l *sqlLexer) stateFn {
249263 case '\n' , '\r' :
250264 return rawState
251265 case utf8 .RuneError :
252- if l .pos - l .start > 0 {
253- l .parts = append (l .parts , l .src [l .start :l .pos ])
254- l .start = l .pos
266+ if width != replacementcharacterwidth {
267+ if l .pos - l .start > 0 {
268+ l .parts = append (l .parts , l .src [l .start :l .pos ])
269+ l .start = l .pos
270+ }
271+ return nil
255272 }
256- return nil
257273 }
258274 }
259275}
@@ -283,11 +299,13 @@ func multilineCommentState(l *sqlLexer) stateFn {
283299 l .nested --
284300
285301 case utf8 .RuneError :
286- if l .pos - l .start > 0 {
287- l .parts = append (l .parts , l .src [l .start :l .pos ])
288- l .start = l .pos
302+ if width != replacementcharacterwidth {
303+ if l .pos - l .start > 0 {
304+ l .parts = append (l .parts , l .src [l .start :l .pos ])
305+ l .start = l .pos
306+ }
307+ return nil
289308 }
290- return nil
291309 }
292310 }
293311}
0 commit comments