1+ // Copyright Joyent, Inc. and other Node contributors.
2+ //
3+ // Permission is hereby granted, free of charge, to any person obtaining a
4+ // copy of this software and associated documentation files (the
5+ // "Software"), to deal in the Software without restriction, including
6+ // without limitation the rights to use, copy, modify, merge, publish,
7+ // distribute, sublicense, and/or sell copies of the Software, and to permit
8+ // persons to whom the Software is furnished to do so, subject to the
9+ // following conditions:
10+ //
11+ // The above copyright notice and this permission notice shall be included
12+ // in all copies or substantial portions of the Software.
13+ //
14+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
122'use strict' ;
223
3- var Buffer = require ( 'safe-buffer' ) . Buffer ;
24+ var _require = require ( 'buffer' ) ,
25+ Buffer = _require . Buffer ;
426
527var isEncoding = Buffer . isEncoding || function ( encoding ) {
628 encoding = '' + encoding ;
@@ -112,10 +134,10 @@ StringDecoder.prototype.fillLast = function (buf) {
112134} ;
113135
114136// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a
115- // continuation byte.
137+ // continuation byte. If an invalid byte is detected, -2 is returned.
116138function utf8CheckByte ( byte ) {
117139 if ( byte <= 0x7F ) return 0 ; else if ( byte >> 5 === 0x06 ) return 2 ; else if ( byte >> 4 === 0x0E ) return 3 ; else if ( byte >> 3 === 0x1E ) return 4 ;
118- return - 1 ;
140+ return byte >> 6 === 0x02 ? - 1 : - 2 ;
119141}
120142
121143// Checks at most 3 bytes at the end of a Buffer in order to detect an
@@ -129,13 +151,13 @@ function utf8CheckIncomplete(self, buf, i) {
129151 if ( nb > 0 ) self . lastNeed = nb - 1 ;
130152 return nb ;
131153 }
132- if ( -- j < i ) return 0 ;
154+ if ( -- j < i || nb === - 2 ) return 0 ;
133155 nb = utf8CheckByte ( buf [ j ] ) ;
134156 if ( nb >= 0 ) {
135157 if ( nb > 0 ) self . lastNeed = nb - 2 ;
136158 return nb ;
137159 }
138- if ( -- j < i ) return 0 ;
160+ if ( -- j < i || nb === - 2 ) return 0 ;
139161 nb = utf8CheckByte ( buf [ j ] ) ;
140162 if ( nb >= 0 ) {
141163 if ( nb > 0 ) {
@@ -149,25 +171,25 @@ function utf8CheckIncomplete(self, buf, i) {
149171// Validates as many continuation bytes for a multi-byte UTF-8 character as
150172// needed or are available. If we see a non-continuation byte where we expect
151173// one, we "replace" the validated continuation bytes we've seen so far with
152- // UTF-8 replacement characters ('\ufffd'), to match v8's UTF-8 decoding
174+ // a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding
153175// behavior. The continuation byte check is included three times in the case
154176// where all of the continuation bytes for a character exist in the same buffer.
155177// It is also done this way as a slight performance increase instead of using a
156178// loop.
157179function utf8CheckExtraBytes ( self , buf , p ) {
158180 if ( ( buf [ 0 ] & 0xC0 ) !== 0x80 ) {
159181 self . lastNeed = 0 ;
160- return '\ufffd' . repeat ( p ) ;
182+ return '\ufffd' ;
161183 }
162184 if ( self . lastNeed > 1 && buf . length > 1 ) {
163185 if ( ( buf [ 1 ] & 0xC0 ) !== 0x80 ) {
164186 self . lastNeed = 1 ;
165- return '\ufffd' . repeat ( p + 1 ) ;
187+ return '\ufffd' ;
166188 }
167189 if ( self . lastNeed > 2 && buf . length > 2 ) {
168190 if ( ( buf [ 2 ] & 0xC0 ) !== 0x80 ) {
169191 self . lastNeed = 2 ;
170- return '\ufffd' . repeat ( p + 2 ) ;
192+ return '\ufffd' ;
171193 }
172194 }
173195 }
@@ -198,11 +220,11 @@ function utf8Text(buf, i) {
198220 return buf . toString ( 'utf8' , i , end ) ;
199221}
200222
201- // For UTF-8, a replacement character for each buffered byte of a ( partial)
202- // character needs to be added to the output .
223+ // For UTF-8, a replacement character is added when ending on a partial
224+ // character.
203225function utf8End ( buf ) {
204226 var r = buf && buf . length ? this . write ( buf ) : '' ;
205- if ( this . lastNeed ) return r + '\ufffd' . repeat ( this . lastTotal - this . lastNeed ) ;
227+ if ( this . lastNeed ) return r + '\ufffd' ;
206228 return r ;
207229}
208230
0 commit comments