File: | builds/wireshark/wireshark/epan/tvbuff_base64.c |
Warning: | line 212, column 9 Potential leak of memory pointed to by 'data' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* tvbuff_base64.c | |||
2 | * Base-64 tvbuff implementation (based on real tvb) | |||
3 | * | |||
4 | * Wireshark - Network traffic analyzer | |||
5 | * By Gerald Combs <[email protected]> | |||
6 | * Copyright 1998 Gerald Combs | |||
7 | * | |||
8 | * SPDX-License-Identifier: GPL-2.0-or-later | |||
9 | */ | |||
10 | ||||
11 | #include "config.h" | |||
12 | ||||
13 | #include <glib.h> | |||
14 | ||||
15 | #include <epan/tvbuff.h> | |||
16 | #include "proto.h" | |||
17 | ||||
18 | /* Copy of glib function modified for base64uri */ | |||
19 | ||||
20 | static const unsigned char mime_base64uri_rank[256] = { | |||
21 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, | |||
22 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, | |||
23 | 255,255,255,255,255,255,255,255,255,255,255, 255,255,63,255,255, | |||
24 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, | |||
25 | 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, | |||
26 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255, 63, | |||
27 | 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, | |||
28 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, | |||
29 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, | |||
30 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, | |||
31 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, | |||
32 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, | |||
33 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, | |||
34 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, | |||
35 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, | |||
36 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, | |||
37 | }; | |||
38 | /** | |||
39 | * Copy of glib function modified for base64uri | |||
40 | * g_base64uri_decode_step: (skip) | |||
41 | * @in: (array length=len) (element-type uint8_t): binary input data | |||
42 | * @len: max length of @in data to decode | |||
43 | * @out: (out caller-allocates) (array) (element-type uint8_t): output buffer | |||
44 | * @state: (inout): Saved state between steps, initialize to 0 | |||
45 | * @save: (inout): Saved state between steps, initialize to 0 | |||
46 | * | |||
47 | * Incrementally decode a sequence of binary data from its Base-64 stringified | |||
48 | * representation. By calling this function multiple times you can convert | |||
49 | * data in chunks to avoid having to have the full encoded data in memory. | |||
50 | * | |||
51 | * The output buffer must be large enough to fit all the data that will | |||
52 | * be written to it. Since base64 encodes 3 bytes in 4 chars you need | |||
53 | * at least: (@len / 4) * 3 + 3 bytes (+ 3 may be needed in case of non-zero | |||
54 | * state). | |||
55 | * | |||
56 | * Returns: The number of bytes of output that was written | |||
57 | * | |||
58 | * Since: 2.12 | |||
59 | **/ | |||
60 | static size_t | |||
61 | g_base64uri_decode_step(const char* in, | |||
62 | size_t len, | |||
63 | unsigned char* out, | |||
64 | int* state, | |||
65 | unsigned* save) | |||
66 | { | |||
67 | const unsigned char* inptr; | |||
68 | unsigned char* outptr; | |||
69 | const unsigned char* inend; | |||
70 | unsigned char c, rank; | |||
71 | unsigned char last[2]; | |||
72 | unsigned int v; | |||
73 | int i; | |||
74 | ||||
75 | g_return_val_if_fail(in != NULL || len == 0, 0)do { if ((in != ((void*)0) || len == 0)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "in != NULL || len == 0" ); return (0); } } while (0); | |||
76 | g_return_val_if_fail(out != NULL, 0)do { if ((out != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "out != NULL"); return (0); } } while (0); | |||
77 | g_return_val_if_fail(state != NULL, 0)do { if ((state != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "state != NULL"); return (0); } } while (0); | |||
78 | g_return_val_if_fail(save != NULL, 0)do { if ((save != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "save != NULL"); return (0); } } while (0); | |||
79 | ||||
80 | if (len == 0) | |||
81 | return 0; | |||
82 | ||||
83 | inend = (const unsigned char*)in + len; | |||
84 | outptr = out; | |||
85 | ||||
86 | /* convert 4 base64 bytes to 3 normal bytes */ | |||
87 | v = *save; | |||
88 | i = *state; | |||
89 | ||||
90 | last[0] = last[1] = 0; | |||
91 | ||||
92 | /* we use the sign in the state to determine if we got a padding character | |||
93 | in the previous sequence */ | |||
94 | if (i < 0) | |||
95 | { | |||
96 | i = -i; | |||
97 | last[0] = '='; | |||
98 | } | |||
99 | ||||
100 | inptr = (const unsigned char*)in; | |||
101 | while (inptr < inend) | |||
102 | { | |||
103 | c = *inptr++; | |||
104 | rank = mime_base64uri_rank[c]; | |||
105 | if (rank != 0xff) | |||
106 | { | |||
107 | last[1] = last[0]; | |||
108 | last[0] = c; | |||
109 | v = (v << 6) | rank; | |||
110 | i++; | |||
111 | if (i == 4) | |||
112 | { | |||
113 | *outptr++ = v >> 16; | |||
114 | if (last[1] != '=') | |||
115 | *outptr++ = v >> 8; | |||
116 | if (last[0] != '=') | |||
117 | *outptr++ = v; | |||
118 | i = 0; | |||
119 | } | |||
120 | } | |||
121 | } | |||
122 | ||||
123 | *save = v; | |||
124 | *state = last[0] == '=' ? -i : i; | |||
125 | ||||
126 | return outptr - out; | |||
127 | } | |||
128 | /** | |||
129 | * Copy of glib function modified for base64uri | |||
130 | * g_base64uri_decode: | |||
131 | * @text: (not nullable): zero-terminated string with base64 text to decode | |||
132 | * @out_len: (out): The length of the decoded data is written here | |||
133 | * | |||
134 | * Decode a sequence of Base-64 encoded text into binary data. Note | |||
135 | * that the returned binary data is not necessarily zero-terminated, | |||
136 | * so it should not be used as a character string. | |||
137 | * | |||
138 | * Returns: (transfer full) (array length=out_len) (element-type uint8_t): | |||
139 | * newly allocated buffer containing the binary data | |||
140 | * that @text represents. The returned buffer must | |||
141 | * be freed with g_free(). | |||
142 | * | |||
143 | * Since: 2.12 | |||
144 | */ | |||
145 | static unsigned char* | |||
146 | g_base64uri_decode(const char* text, | |||
147 | size_t* out_len) | |||
148 | { | |||
149 | unsigned char* ret; | |||
150 | size_t input_length; | |||
151 | int state = 0; | |||
152 | unsigned save = 0; | |||
153 | ||||
154 | g_return_val_if_fail(text != NULL, NULL)do { if ((text != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "text != NULL"); return (((void*)0)); } } while (0); | |||
155 | g_return_val_if_fail(out_len != NULL, NULL)do { if ((out_len != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "out_len != NULL" ); return (((void*)0)); } } while (0); | |||
156 | ||||
157 | input_length = strlen(text); | |||
158 | ||||
159 | /* We can use a smaller limit here, since we know the saved state is 0, | |||
160 | +1 used to avoid calling g_malloc0(0), and hence returning NULL */ | |||
161 | ret = (unsigned char * )g_malloc0((input_length / 4) * 3 + 1); | |||
162 | ||||
163 | *out_len = g_base64uri_decode_step(text, input_length, ret, &state, &save); | |||
164 | ||||
165 | return ret; | |||
166 | } | |||
167 | ||||
168 | tvbuff_t * | |||
169 | base64_to_tvb(tvbuff_t *parent, const char *base64) | |||
170 | { | |||
171 | tvbuff_t *tvb; | |||
172 | char *data; | |||
173 | size_t len; | |||
174 | ||||
175 | data = g_base64_decode(base64, &len); | |||
176 | tvb = tvb_new_child_real_data(parent, (const uint8_t *)data, (int)len, (int)len); | |||
177 | ||||
178 | tvb_set_free_cb(tvb, g_free); | |||
179 | ||||
180 | return tvb; | |||
181 | } | |||
182 | ||||
183 | tvbuff_t* | |||
184 | base64_tvb_to_new_tvb(tvbuff_t* parent, int offset, int length) | |||
185 | { | |||
186 | tvbuff_t* tvb; | |||
187 | char* data, *tmp; | |||
188 | size_t len; | |||
189 | ||||
190 | tmp = tvb_get_string_enc(NULL((void*)0), parent, offset, length, ENC_ASCII0x00000000); | |||
191 | data = g_base64_decode(tmp, &len); | |||
192 | wmem_free(NULL((void*)0), tmp); | |||
193 | ||||
194 | tvb = tvb_new_child_real_data(parent, (const uint8_t*)data, (int)len, (int)len); | |||
195 | ||||
196 | tvb_set_free_cb(tvb, g_free); | |||
197 | ||||
198 | return tvb; | |||
199 | } | |||
200 | ||||
201 | tvbuff_t* | |||
202 | base64uri_tvb_to_new_tvb(tvbuff_t* parent, int offset, int length) | |||
203 | { | |||
204 | tvbuff_t* tvb; | |||
205 | char* data, *tmp; | |||
206 | size_t len = 0; | |||
207 | ||||
208 | tmp = tvb_get_string_enc(NULL((void*)0), parent, offset, length, ENC_ASCII0x00000000); | |||
209 | data = g_base64uri_decode(tmp, &len); | |||
| ||||
210 | wmem_free(NULL((void*)0), tmp); | |||
211 | ||||
212 | tvb = tvb_new_child_real_data(parent, (const uint8_t*)data, (int)len, (int)len); | |||
| ||||
213 | ||||
214 | tvb_set_free_cb(tvb, g_free); | |||
215 | ||||
216 | return tvb; | |||
217 | } | |||
218 | /* | |||
219 | * Editor modelines - https://www.wireshark.org/tools/modelines.html | |||
220 | * | |||
221 | * Local Variables: | |||
222 | * c-basic-offset: 2 | |||
223 | * tab-width: 8 | |||
224 | * indent-tabs-mode: nil | |||
225 | * End: | |||
226 | * | |||
227 | * ex: set shiftwidth=2 tabstop=8 expandtab: | |||
228 | * :indentSize=2:tabSize=8:noTabs=true: | |||
229 | */ |