@@ -1019,36 +1019,59 @@ function asciiWrite (buf, string, offset, length) {
1019
1019
}
1020
1020
1021
1021
function 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
1024
1023
const dst = buf
1025
1024
1026
- let srcLen = eq >= 0 ? eq : src . length
1025
+ let srcLen = src . length
1027
1026
let srcPos = 0
1028
1027
let dstLen = length
1029
1028
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
+ }
1030
1050
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 )
1040
1054
1041
- srcLen -= 4
1042
- dstLen -= 3
1043
- }
1055
+ srcLen -= 4
1056
+ dstLen -= 3
1057
+ }
1044
1058
1045
- {
1046
1059
let w1 , w2 , w3 , w4
1060
+ let state = 0
1047
1061
1048
1062
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 --
1050
1068
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 ) {
1052
1075
case 0 :
1053
1076
w1 = w
1054
1077
break
@@ -1066,12 +1089,18 @@ function base64Write (buf, string, offset, length) {
1066
1089
w4 = w
1067
1090
dst [ dstPos ++ ] = ( w3 << 6 ) | ( w4 >> 0 )
1068
1091
dstLen --
1092
+ if ( invalid ) {
1093
+ // Retry fast parsing.
1094
+ invalid = false
1095
+ continue retry // eslint-disable-line
1096
+ }
1069
1097
break
1070
1098
}
1071
1099
1072
- srcPos ++
1073
- srcLen --
1100
+ state ++
1074
1101
}
1102
+
1103
+ break
1075
1104
}
1076
1105
1077
1106
return dstPos - offset
0 commit comments