@@ -41,26 +41,32 @@ library Base64 {
41
41
let tablePtr := add (table, 1 )
42
42
43
43
// Prepare result pointer, jump over length
44
- let resultPtr := add (result, 32 )
44
+ let resultPtr := add (result, 0x20 )
45
+ let dataPtr := data
46
+ let endPtr := add (data, mload (data))
47
+
48
+ // In some cases, the last iteration will read bytes after the end of the data. We cache the value, and
49
+ // set it to zero to make sure no dirty bytes are read in that section.
50
+ let afterPtr := add (endPtr, 0x20 )
51
+ let afterCache := mload (afterPtr)
52
+ mstore (afterPtr, 0x00 )
45
53
46
54
// Run over the input, 3 bytes at a time
47
55
for {
48
- let dataPtr := data
49
- let endPtr := add (data, mload (data))
56
+
50
57
} lt (dataPtr, endPtr) {
51
58
52
59
} {
53
60
// Advance 3 bytes
54
61
dataPtr := add (dataPtr, 3 )
55
62
let input := mload (dataPtr)
56
63
57
- // To write each character, shift the 3 bytes (18 bits) chunk
64
+ // To write each character, shift the 3 byte (24 bits) chunk
58
65
// 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
59
- // and apply logical AND with 0x3F which is the number of
60
- // the previous character in the ASCII table prior to the Base64 Table
61
- // The result is then added to the table to get the character to write,
62
- // and finally write it in the result pointer but with a left shift
63
- // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits
66
+ // and apply logical AND with 0x3F to bitmask the least significant 6 bits.
67
+ // Use this as an index into the lookup table, mload an entire word
68
+ // so the desired character is in the least significant byte, and
69
+ // mstore8 this least significant byte into the result and continue.
64
70
65
71
mstore8 (resultPtr, mload (add (tablePtr, and (shr (18 , input), 0x3F ))))
66
72
resultPtr := add (resultPtr, 1 ) // Advance
@@ -75,6 +81,9 @@ library Base64 {
75
81
resultPtr := add (resultPtr, 1 ) // Advance
76
82
}
77
83
84
+ // Reset the value that was cached
85
+ mstore (afterPtr, afterCache)
86
+
78
87
// When data `bytes` is not exactly 3 bytes long
79
88
// it is padded with `=` characters at the end
80
89
switch mod (mload (data), 3 )
0 commit comments