Avoid integer overflows in the base64 functions. Fixes CVE-2008-4316
[platform/upstream/glib.git] / glib / gbase64.c
1 /* gbase64.c - Base64 encoding/decoding
2  *
3  *  Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
4  *  Copyright (C) 2000-2003 Ximian Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  * This is based on code in camel, written by:
22  *    Michael Zucchi <notzed@ximian.com>
23  *    Jeffrey Stedfast <fejj@ximian.com>
24  */
25
26 #include "config.h"
27
28 #include <string.h>
29
30 #include "gbase64.h"
31 #include "glib.h"
32 #include "glibintl.h"
33
34 #include "galias.h"
35
36 static const char base64_alphabet[] =
37         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
38
39 /**
40  * g_base64_encode_step:
41  * @in: the binary data to encode
42  * @len: the length of @in
43  * @break_lines: whether to break long lines
44  * @out: pointer to destination buffer
45  * @state: Saved state between steps, initialize to 0
46  * @save: Saved state between steps, initialize to 0
47  *
48  * Incrementally encode a sequence of binary data into its Base-64 stringified
49  * representation. By calling this function multiple times you can convert 
50  * data in chunks to avoid having to have the full encoded data in memory.
51  *
52  * When all of the data has been converted you must call 
53  * g_base64_encode_close() to flush the saved state.
54  *
55  * The output buffer must be large enough to fit all the data that will
56  * be written to it. Due to the way base64 encodes you will need
57  * at least: (@len / 3 + 1) * 4 + 4 bytes (+ 4 may be needed in case of
58  * non-zero state). If you enable line-breaking you will need at least:
59  * ((@len / 3 + 1) * 4 + 4) / 72 + 1 bytes of extra space.
60  *
61  * @break_lines is typically used when putting base64-encoded data in emails.
62  * It breaks the lines at 72 columns instead of putting all of the text on 
63  * the same line. This avoids problems with long lines in the email system.
64  *
65  * Return value: The number of bytes of output that was written
66  *
67  * Since: 2.12
68  */
69 gsize
70 g_base64_encode_step (const guchar *in, 
71                       gsize         len, 
72                       gboolean      break_lines, 
73                       gchar        *out, 
74                       gint         *state, 
75                       gint         *save)
76 {
77   char *outptr;
78   const guchar *inptr;
79   
80   g_return_val_if_fail (in != NULL, 0);
81   g_return_val_if_fail (out != NULL, 0);
82   g_return_val_if_fail (state != NULL, 0);
83   g_return_val_if_fail (save != NULL, 0);
84
85   if (len <= 0)
86     return 0;
87   
88   inptr = in;
89   outptr = out;
90   
91   if (len + ((char *) save) [0] > 2)
92     {
93       const guchar *inend = in+len-2;
94       int c1, c2, c3;
95       int already;
96       
97       already = *state;
98       
99       switch (((char *) save) [0])
100         {       
101         case 1: 
102           c1 = ((unsigned char *) save) [1]; 
103           goto skip1;
104         case 2: 
105           c1 = ((unsigned char *) save) [1];
106           c2 = ((unsigned char *) save) [2]; 
107           goto skip2;
108         }
109       
110       /* 
111        * yes, we jump into the loop, no i'm not going to change it, 
112        * it's beautiful! 
113        */
114       while (inptr < inend)
115         {
116           c1 = *inptr++;
117         skip1:
118           c2 = *inptr++;
119         skip2:
120           c3 = *inptr++;
121           *outptr++ = base64_alphabet [ c1 >> 2 ];
122           *outptr++ = base64_alphabet [ c2 >> 4 | 
123                                         ((c1&0x3) << 4) ];
124           *outptr++ = base64_alphabet [ ((c2 &0x0f) << 2) | 
125                                         (c3 >> 6) ];
126           *outptr++ = base64_alphabet [ c3 & 0x3f ];
127           /* this is a bit ugly ... */
128           if (break_lines && (++already) >= 19)
129             {
130               *outptr++ = '\n';
131               already = 0;
132             }
133         }
134       
135       ((char *)save)[0] = 0;
136       len = 2 - (inptr - inend);
137       *state = already;
138     }
139   
140   if (len>0)
141     {
142       char *saveout;
143       
144       /* points to the slot for the next char to save */
145       saveout = & (((char *)save)[1]) + ((char *)save)[0];
146       
147       /* len can only be 0 1 or 2 */
148       switch(len)
149         {
150         case 2: *saveout++ = *inptr++;
151         case 1: *saveout++ = *inptr++;
152         }
153       ((char *)save)[0] += len;
154     }
155   
156   return outptr - out;
157 }
158
159 /**
160  * g_base64_encode_close:
161  * @break_lines: whether to break long lines
162  * @out: pointer to destination buffer
163  * @state: Saved state from g_base64_encode_step()
164  * @save: Saved state from g_base64_encode_step()
165  *
166  * Flush the status from a sequence of calls to g_base64_encode_step().
167  *
168  * Return value: The number of bytes of output that was written
169  *
170  * Since: 2.12
171  */
172 gsize
173 g_base64_encode_close (gboolean  break_lines,
174                        gchar    *out, 
175                        gint     *state, 
176                        gint     *save)
177 {
178   int c1, c2;
179   char *outptr = out;
180
181   g_return_val_if_fail (out != NULL, 0);
182   g_return_val_if_fail (state != NULL, 0);
183   g_return_val_if_fail (save != NULL, 0);
184
185   c1 = ((unsigned char *) save) [1];
186   c2 = ((unsigned char *) save) [2];
187   
188   switch (((char *) save) [0])
189     {
190     case 2:
191       outptr [2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
192       g_assert (outptr [2] != 0);
193       goto skip;
194     case 1:
195       outptr[2] = '=';
196     skip:
197       outptr [0] = base64_alphabet [ c1 >> 2 ];
198       outptr [1] = base64_alphabet [ c2 >> 4 | ( (c1&0x3) << 4 )];
199       outptr [3] = '=';
200       outptr += 4;
201       break;
202     }
203   if (break_lines)
204     *outptr++ = '\n';
205   
206   *save = 0;
207   *state = 0;
208   
209   return outptr - out;
210 }
211
212 /**
213  * g_base64_encode:
214  * @data: the binary data to encode
215  * @len: the length of @data
216  *
217  * Encode a sequence of binary data into its Base-64 stringified
218  * representation.
219  *
220  * Return value: a newly allocated, zero-terminated Base-64 encoded
221  *               string representing @data. The returned string must 
222  *               be freed with g_free().
223  *
224  * Since: 2.12
225  */
226 gchar *
227 g_base64_encode (const guchar *data, 
228                  gsize         len)
229 {
230   gchar *out;
231   gint state = 0, outlen;
232   gint save = 0;
233
234   g_return_val_if_fail (data != NULL, NULL);
235   g_return_val_if_fail (len > 0, NULL);
236
237   /* We can use a smaller limit here, since we know the saved state is 0,
238      +1 is needed for trailing \0, also check for unlikely integer overflow */
239   if (len >= ((G_MAXSIZE - 1) / 4 - 1) * 3)
240     g_error("%s: input too large for Base64 encoding (%"G_GSIZE_FORMAT" chars)",
241         G_STRLOC, len);
242
243   out = g_malloc ((len / 3 + 1) * 4 + 1);
244
245   outlen = g_base64_encode_step (data, len, FALSE, out, &state, &save);
246   outlen += g_base64_encode_close (FALSE, out + outlen, &state, &save);
247   out[outlen] = '\0';
248
249   return (gchar *) out;
250 }
251
252 static const unsigned char mime_base64_rank[256] = {
253   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
254   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255   255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
256    52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255,  0,255,255,
257   255,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
258    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
259   255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
260    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
261   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
262   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
263   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
264   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
265   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
266   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
267   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
268   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
269 };
270
271 /**
272  * g_base64_decode_step: 
273  * @in: binary input data
274  * @len: max length of @in data to decode
275  * @out: output buffer
276  * @state: Saved state between steps, initialize to 0
277  * @save: Saved state between steps, initialize to 0
278  *
279  * Incrementally decode a sequence of binary data from its Base-64 stringified
280  * representation. By calling this function multiple times you can convert 
281  * data in chunks to avoid having to have the full encoded data in memory.
282  *
283  * The output buffer must be large enough to fit all the data that will
284  * be written to it. Since base64 encodes 3 bytes in 4 chars you need
285  * at least: (@len / 4) * 3 + 3 bytes (+ 3 may be needed in case of non-zero
286  * state).
287  * 
288  * Return value: The number of bytes of output that was written
289  *
290  * Since: 2.12
291  **/
292 gsize
293 g_base64_decode_step (const gchar  *in, 
294                       gsize         len, 
295                       guchar       *out, 
296                       gint         *state, 
297                       guint        *save)
298 {
299   const guchar *inptr;
300   guchar *outptr;
301   const guchar *inend;
302   guchar c, rank;
303   guchar last[2];
304   unsigned int v;
305   int i;
306
307   g_return_val_if_fail (in != NULL, 0);
308   g_return_val_if_fail (out != NULL, 0);
309   g_return_val_if_fail (state != NULL, 0);
310   g_return_val_if_fail (save != NULL, 0);
311
312   if (len <= 0)
313     return 0;
314   
315   inend = (const guchar *)in+len;
316   outptr = out;
317   
318   /* convert 4 base64 bytes to 3 normal bytes */
319   v=*save;
320   i=*state;
321   inptr = (const guchar *)in;
322   last[0] = last[1] = 0;
323   while (inptr < inend)
324     {
325       c = *inptr++;
326       rank = mime_base64_rank [c];
327       if (rank != 0xff)
328         {
329           last[1] = last[0];
330           last[0] = c;
331           v = (v<<6) | rank;
332           i++;
333           if (i==4)
334             {
335               *outptr++ = v>>16;
336               if (last[1] != '=')
337                 *outptr++ = v>>8;
338               if (last[0] != '=')
339                 *outptr++ = v;
340               i=0;
341             }
342         }
343     }
344   
345   *save = v;
346   *state = i;
347   
348   return outptr - out;
349 }
350
351 /**
352  * g_base64_decode:
353  * @text: zero-terminated string with base64 text to decode
354  * @out_len: The length of the decoded data is written here
355  *
356  * Decode a sequence of Base-64 encoded text into binary data
357  *
358  * Return value: a newly allocated buffer containing the binary data
359  *               that @text represents. The returned buffer must
360  *               be freed with g_free().
361  *
362  * Since: 2.12
363  */
364 guchar *
365 g_base64_decode (const gchar *text,
366                  gsize       *out_len)
367 {
368   guchar *ret;
369   gsize input_length;
370   gint state = 0;
371   guint save = 0;
372   
373   g_return_val_if_fail (text != NULL, NULL);
374   g_return_val_if_fail (out_len != NULL, NULL);
375
376   input_length = strlen (text);
377
378   g_return_val_if_fail (input_length > 1, NULL);
379
380   /* We can use a smaller limit here, since we know the saved state is 0,
381      +1 used to avoid calling g_malloc0(0), and hence retruning NULL */
382   ret = g_malloc0 ((input_length / 4) * 3 + 1);
383   
384   *out_len = g_base64_decode_step (text, input_length, ret, &state, &save);
385   
386   return ret; 
387 }
388  
389 /**
390  * g_base64_decode_inplace:
391  * @text: zero-terminated string with base64 text to decode
392  * @out_len: The length of the decoded data is written here
393  *
394  * Decode a sequence of Base-64 encoded text into binary data
395  * by overwriting the input data.
396  *
397  * Return value: The binary data that @text responds. This pointer
398  *               is the same as the input @text.
399  *
400  * Since: 2.20
401  */
402 guchar *
403 g_base64_decode_inplace (gchar *text,
404                          gsize *out_len)
405 {
406   gint input_length, state = 0;
407   guint save = 0;
408   
409   g_return_val_if_fail (text != NULL, NULL);
410   g_return_val_if_fail (out_len != NULL, NULL);
411
412   input_length = strlen (text);
413
414   g_return_val_if_fail (input_length > 1, NULL);
415
416   *out_len = g_base64_decode_step (text, input_length, (guchar *) text, &state, &save);
417   
418   return text; 
419 }
420
421
422 #define __G_BASE64_C__
423 #include "galiasdef.c"