@@ -1019,36 +1019,59 @@ function asciiWrite (buf, string, offset, length) {
10191019}
10201020
10211021function base64Write ( buf , string , offset , length ) {
1022- const src = string . replace ( / [ ^ + / 0 - 9 A - Z a - z - _ = ] / g, '' )
1023- const eq = src . indexOf ( '=' )
1022+ const src = string
10241023 const dst = buf
10251024
1026- let srcLen = eq >= 0 ? eq : src . length
1025+ let srcLen = src . length
10271026 let srcPos = 0
10281027 let dstLen = length
10291028 let dstPos = offset
1029+ let invalid = false
1030+
1031+ if ( srcLen > 0 && src [ srcLen - 1 ] === '=' ) srcLen -= 1
1032+ if ( srcLen > 0 && src [ srcLen - 1 ] === '=' ) srcLen -= 1
1033+
1034+ retry: for ( ; ; ) { // eslint-disable-line
1035+ while ( srcLen >= 4 && dstLen >= 3 ) {
1036+ const c1 = src . charCodeAt ( srcPos ++ )
1037+ const c2 = src . charCodeAt ( srcPos ++ )
1038+ const c3 = src . charCodeAt ( srcPos ++ )
1039+ const c4 = src . charCodeAt ( srcPos ++ )
1040+ const t1 = base64Table [ c1 & 0x7f ]
1041+ const t2 = base64Table [ c2 & 0x7f ]
1042+ const t3 = base64Table [ c3 & 0x7f ]
1043+ const t4 = base64Table [ c4 & 0x7f ]
1044+
1045+ if ( ( c1 | c2 | c3 | c4 | t1 | t2 | t3 | t4 ) & ~ 0x7f ) {
1046+ srcPos -= 4
1047+ invalid = true // Slow parsing until we recover.
1048+ break
1049+ }
10301050
1031- while ( srcLen >= 4 && dstLen >= 3 ) {
1032- const t1 = base64Table [ src . charCodeAt ( srcPos ++ ) ]
1033- const t2 = base64Table [ src . charCodeAt ( srcPos ++ ) ]
1034- const t3 = base64Table [ src . charCodeAt ( srcPos ++ ) ]
1035- const t4 = base64Table [ src . charCodeAt ( srcPos ++ ) ]
1036-
1037- dst [ dstPos ++ ] = ( t1 << 2 ) | ( t2 >> 4 )
1038- dst [ dstPos ++ ] = ( t2 << 4 ) | ( t3 >> 2 )
1039- dst [ dstPos ++ ] = ( t3 << 6 ) | ( t4 >> 0 )
1051+ dst [ dstPos ++ ] = ( t1 << 2 ) | ( t2 >> 4 )
1052+ dst [ dstPos ++ ] = ( t2 << 4 ) | ( t3 >> 2 )
1053+ dst [ dstPos ++ ] = ( t3 << 6 ) | ( t4 >> 0 )
10401054
1041- srcLen -= 4
1042- dstLen -= 3
1043- }
1055+ srcLen -= 4
1056+ dstLen -= 3
1057+ }
10441058
1045- {
10461059 let w1 , w2 , w3 , w4
1060+ let state = 0
10471061
10481062 while ( srcLen && dstLen ) {
1049- const w = base64Table [ src . charCodeAt ( srcPos ) ]
1063+ const c = src . charCodeAt ( srcPos )
1064+ const w = base64Table [ c & 0x7f ]
1065+
1066+ srcPos ++
1067+ srcLen --
10501068
1051- switch ( srcPos & 3 ) {
1069+ if ( ( c | w ) & ~ 0x7f ) {
1070+ if ( c === 0x3d ) break // Stop on `=`
1071+ continue // Skip invalid
1072+ }
1073+
1074+ switch ( state & 3 ) {
10521075 case 0 :
10531076 w1 = w
10541077 break
@@ -1066,12 +1089,18 @@ function base64Write (buf, string, offset, length) {
10661089 w4 = w
10671090 dst [ dstPos ++ ] = ( w3 << 6 ) | ( w4 >> 0 )
10681091 dstLen --
1092+ if ( invalid ) {
1093+ // Retry fast parsing.
1094+ invalid = false
1095+ continue retry // eslint-disable-line
1096+ }
10691097 break
10701098 }
10711099
1072- srcPos ++
1073- srcLen --
1100+ state ++
10741101 }
1102+
1103+ break
10751104 }
10761105
10771106 return dstPos - offset
0 commit comments