@@ -21,9 +21,25 @@ constant aleph = {
2121 '0' ,'1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,'8' ,'9' ,'+' ,'/'
2222}
2323
24- --#
25- --# - see also ccha in which inverted decode table is built.
26- --#
24+ --# Base64 decode table (-1 is invalid character)
25+ constant ccha = {
26+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
27+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
28+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52,
29+ 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1,
30+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
31+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1,
32+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
33+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1,
34+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
35+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
37+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
38+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
39+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
40+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
41+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
42+ }
2743--# Pad character is '=' (61)
2844--#
2945--# encoded output of encode is mo more that 76 characters each.
@@ -154,16 +170,16 @@ end function
154170-- # ##in## ~-- must be a simple sequence of length ##4## to ##76## .
155171--
156172-- Returns:
157- -- A **sequence**, base256 decode of passed sequence.
158- -- the length of data to decode must be a multiple of ##4## .
173+ -- A **sequence**, base256 decode of passed sequence if the length of
174+ -- the data to decode is a multiple of ##4## and a valid Base64 code.
175+ -- Otherwise, -1 is returned.
159176--
160177-- Comments:
161178-- The calling program is expected to strip newlines and so on before calling.
162179--
163180public function decode (sequence in)
164- integer len, oidx, case3, tmp
181+ integer len, oidx, case3, tmp, index
165182 sequence result
166- sequence ccha
167183
168184 -- TODO: Surely this is not the most efficient way of doing this
169185 in = search:match_replace("\r\n " , in, "" )
@@ -172,23 +188,21 @@ public function decode(sequence in)
172188 if remainder (len, 4) != 0 then
173189 return -1
174190 end if
175-
191+
176192 oidx = (len / 4) * 3
177193 case3 = 3
178-
179- while in[len] = '=' do --# should only happen 0 1 or 2 times
194+
195+ tmp = len
196+ while len > 0 and in[len] = '=' do --# should only happen 0 1 or 2 times
180197 oidx -= 1
181198 case3 = nc3[case3]
182199 len -= 1
183200 end while
184201
185- --#
186- --# invert aleph to a decode table
187- --#
188- ccha = repeat (0, 256)
189- for i = 1 to 64 do
190- ccha[aleph[i]] = i - 1
191- end for
202+ if tmp - len > 2 --# too many pad characters
203+ then
204+ return -1
205+ end if
192206
193207 result = repeat ('?' , oidx)
194208 for i = oidx to 1 by -1 do
@@ -201,7 +215,19 @@ public function decode(sequence in)
201215 --# dmul = {4,16,64}
202216 --# ddiv = {16,4,1}
203217 --#
204- tmp = remainder (ccha[in[len - 1]], drem[case3]) * dmul[case3]
218+ index = ccha[in[len - 1]]
219+ if index < 0 --# Invalid character
220+ then
221+ return -1
222+ end if
223+
224+ tmp = remainder (index, drem[case3]) * dmul[case3]
225+ index = ccha[in[len]]
226+ if index < 0 --# Invalid character
227+ then
228+ return -1
229+ end if
230+
205231 tmp += floor (ccha[in[len]] / ddiv[case3])
206232 result[i] = tmp
207233 len -= ldrop[case3]
0 commit comments