diff options
Diffstat (limited to 'src/gnsrecord/gnsrecord_serialization.c')
-rw-r--r-- | src/gnsrecord/gnsrecord_serialization.c | 158 |
1 files changed, 126 insertions, 32 deletions
diff --git a/src/gnsrecord/gnsrecord_serialization.c b/src/gnsrecord/gnsrecord_serialization.c index 190f62fc2..934d36102 100644 --- a/src/gnsrecord/gnsrecord_serialization.c +++ b/src/gnsrecord/gnsrecord_serialization.c | |||
@@ -2,20 +2,18 @@ | |||
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2009-2013 GNUnet e.V. | 3 | Copyright (C) 2009-2013 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software: you can redistribute it and/or modify it |
6 | it under the terms of the GNU General Public License as published | 6 | under the terms of the GNU Affero General Public License as published |
7 | by the Free Software Foundation; either version 3, or (at your | 7 | by the Free Software Foundation, either version 3 of the License, |
8 | option) any later version. | 8 | or (at your option) any later version. |
9 | 9 | ||
10 | GNUnet is distributed in the hope that it will be useful, but | 10 | GNUnet is distributed in the hope that it will be useful, but |
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU General Public License | 15 | You should have received a copy of the GNU Affero General Public License |
16 | along with GNUnet; see the file COPYING. If not, write to the | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | 17 | */ |
20 | 18 | ||
21 | /** | 19 | /** |
@@ -37,6 +35,12 @@ | |||
37 | 35 | ||
38 | #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) | 36 | #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) |
39 | 37 | ||
38 | /** | ||
39 | * Set to 1 to check that all records are well-formed (can be converted | ||
40 | * to string) during serialization/deserialization. | ||
41 | */ | ||
42 | #define DEBUG_GNSRECORDS 0 | ||
43 | |||
40 | GNUNET_NETWORK_STRUCT_BEGIN | 44 | GNUNET_NETWORK_STRUCT_BEGIN |
41 | 45 | ||
42 | 46 | ||
@@ -78,22 +82,63 @@ GNUNET_NETWORK_STRUCT_END | |||
78 | * | 82 | * |
79 | * @param rd_count number of records in the rd array | 83 | * @param rd_count number of records in the rd array |
80 | * @param rd array of #GNUNET_GNSRECORD_Data with @a rd_count elements | 84 | * @param rd array of #GNUNET_GNSRECORD_Data with @a rd_count elements |
81 | * @return the required size to serialize | 85 | * @return the required size to serialize, -1 on error |
82 | */ | 86 | */ |
83 | size_t | 87 | ssize_t |
84 | GNUNET_GNSRECORD_records_get_size (unsigned int rd_count, | 88 | GNUNET_GNSRECORD_records_get_size (unsigned int rd_count, |
85 | const struct GNUNET_GNSRECORD_Data *rd) | 89 | const struct GNUNET_GNSRECORD_Data *rd) |
86 | { | 90 | { |
87 | unsigned int i; | ||
88 | size_t ret; | 91 | size_t ret; |
89 | 92 | ||
93 | if (0 == rd_count) | ||
94 | return 0; | ||
95 | |||
90 | ret = sizeof (struct NetworkRecord) * rd_count; | 96 | ret = sizeof (struct NetworkRecord) * rd_count; |
91 | for (i=0;i<rd_count;i++) | 97 | for (unsigned int i=0;i<rd_count;i++) |
92 | { | 98 | { |
93 | GNUNET_assert ((ret + rd[i].data_size) >= ret); | 99 | if ((ret + rd[i].data_size) < ret) |
100 | { | ||
101 | GNUNET_break (0); | ||
102 | return -1; | ||
103 | } | ||
94 | ret += rd[i].data_size; | 104 | ret += rd[i].data_size; |
105 | #if DEBUG_GNSRECORDS | ||
106 | { | ||
107 | char *str; | ||
108 | |||
109 | str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, | ||
110 | rd[i].data, | ||
111 | rd[i].data_size); | ||
112 | if (NULL == str) | ||
113 | { | ||
114 | GNUNET_break_op (0); | ||
115 | return -1; | ||
116 | } | ||
117 | GNUNET_free (str); | ||
118 | } | ||
119 | #endif | ||
95 | } | 120 | } |
96 | return ret; | 121 | if (ret > SSIZE_MAX) |
122 | { | ||
123 | GNUNET_break (0); | ||
124 | return -1; | ||
125 | } | ||
126 | //Do not pad PKEY | ||
127 | if (GNUNET_GNSRECORD_TYPE_PKEY == rd->record_type) | ||
128 | return ret; | ||
129 | /** | ||
130 | * Efficiently round up to the next | ||
131 | * power of 2 for padding | ||
132 | * https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 | ||
133 | */ | ||
134 | ret--; | ||
135 | ret |= ret >> 1; | ||
136 | ret |= ret >> 2; | ||
137 | ret |= ret >> 4; | ||
138 | ret |= ret >> 8; | ||
139 | ret |= ret >> 16; | ||
140 | ret++; | ||
141 | return (ssize_t) ret; | ||
97 | } | 142 | } |
98 | 143 | ||
99 | 144 | ||
@@ -108,16 +153,15 @@ GNUNET_GNSRECORD_records_get_size (unsigned int rd_count, | |||
108 | */ | 153 | */ |
109 | ssize_t | 154 | ssize_t |
110 | GNUNET_GNSRECORD_records_serialize (unsigned int rd_count, | 155 | GNUNET_GNSRECORD_records_serialize (unsigned int rd_count, |
111 | const struct GNUNET_GNSRECORD_Data *rd, | 156 | const struct GNUNET_GNSRECORD_Data *rd, |
112 | size_t dest_size, | 157 | size_t dest_size, |
113 | char *dest) | 158 | char *dest) |
114 | { | 159 | { |
115 | struct NetworkRecord rec; | 160 | struct NetworkRecord rec; |
116 | unsigned int i; | ||
117 | size_t off; | 161 | size_t off; |
118 | 162 | ||
119 | off = 0; | 163 | off = 0; |
120 | for (i=0;i<rd_count;i++) | 164 | for (unsigned int i=0;i<rd_count;i++) |
121 | { | 165 | { |
122 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 166 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
123 | "Serializing record %u with flags %d and expiration time %llu\n", | 167 | "Serializing record %u with flags %d and expiration time %llu\n", |
@@ -128,20 +172,46 @@ GNUNET_GNSRECORD_records_serialize (unsigned int rd_count, | |||
128 | rec.data_size = htonl ((uint32_t) rd[i].data_size); | 172 | rec.data_size = htonl ((uint32_t) rd[i].data_size); |
129 | rec.record_type = htonl (rd[i].record_type); | 173 | rec.record_type = htonl (rd[i].record_type); |
130 | rec.flags = htonl (rd[i].flags); | 174 | rec.flags = htonl (rd[i].flags); |
131 | if (off + sizeof (rec) > dest_size) | 175 | if ( (off + sizeof (rec) > dest_size) || |
176 | (off + sizeof (rec) < off) ) | ||
177 | { | ||
178 | GNUNET_break (0); | ||
132 | return -1; | 179 | return -1; |
180 | } | ||
133 | GNUNET_memcpy (&dest[off], | 181 | GNUNET_memcpy (&dest[off], |
134 | &rec, | 182 | &rec, |
135 | sizeof (rec)); | 183 | sizeof (rec)); |
136 | off += sizeof (rec); | 184 | off += sizeof (rec); |
137 | if (off + rd[i].data_size > dest_size) | 185 | if ( (off + rd[i].data_size > dest_size) || |
186 | (off + rd[i].data_size < off) ) | ||
187 | { | ||
188 | GNUNET_break (0); | ||
138 | return -1; | 189 | return -1; |
190 | } | ||
139 | GNUNET_memcpy (&dest[off], | 191 | GNUNET_memcpy (&dest[off], |
140 | rd[i].data, | 192 | rd[i].data, |
141 | rd[i].data_size); | 193 | rd[i].data_size); |
142 | off += rd[i].data_size; | 194 | off += rd[i].data_size; |
195 | #if DEBUG_GNSRECORDS | ||
196 | { | ||
197 | char *str; | ||
198 | |||
199 | str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, | ||
200 | rd[i].data, | ||
201 | rd[i].data_size); | ||
202 | if (NULL == str) | ||
203 | { | ||
204 | GNUNET_break_op (0); | ||
205 | return -1; | ||
206 | } | ||
207 | GNUNET_free (str); | ||
208 | } | ||
209 | #endif | ||
143 | } | 210 | } |
144 | return off; | 211 | memset (&dest[off], |
212 | 0, | ||
213 | dest_size-off); | ||
214 | return dest_size; | ||
145 | } | 215 | } |
146 | 216 | ||
147 | 217 | ||
@@ -156,29 +226,53 @@ GNUNET_GNSRECORD_records_serialize (unsigned int rd_count, | |||
156 | */ | 226 | */ |
157 | int | 227 | int |
158 | GNUNET_GNSRECORD_records_deserialize (size_t len, | 228 | GNUNET_GNSRECORD_records_deserialize (size_t len, |
159 | const char *src, | 229 | const char *src, |
160 | unsigned int rd_count, | 230 | unsigned int rd_count, |
161 | struct GNUNET_GNSRECORD_Data *dest) | 231 | struct GNUNET_GNSRECORD_Data *dest) |
162 | { | 232 | { |
163 | struct NetworkRecord rec; | 233 | struct NetworkRecord rec; |
164 | unsigned int i; | ||
165 | size_t off; | 234 | size_t off; |
166 | 235 | ||
167 | off = 0; | 236 | off = 0; |
168 | for (i=0;i<rd_count;i++) | 237 | for (unsigned int i=0;i<rd_count;i++) |
169 | { | 238 | { |
170 | if (off + sizeof (rec) > len) | 239 | if ( (off + sizeof (rec) > len) || |
240 | (off + sizeof (rec) < off) ) | ||
241 | { | ||
242 | GNUNET_break_op (0); | ||
171 | return GNUNET_SYSERR; | 243 | return GNUNET_SYSERR; |
172 | GNUNET_memcpy (&rec, &src[off], sizeof (rec)); | 244 | } |
245 | GNUNET_memcpy (&rec, | ||
246 | &src[off], | ||
247 | sizeof (rec)); | ||
173 | dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time); | 248 | dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time); |
174 | dest[i].data_size = ntohl ((uint32_t) rec.data_size); | 249 | dest[i].data_size = ntohl ((uint32_t) rec.data_size); |
175 | dest[i].record_type = ntohl (rec.record_type); | 250 | dest[i].record_type = ntohl (rec.record_type); |
176 | dest[i].flags = ntohl (rec.flags); | 251 | dest[i].flags = ntohl (rec.flags); |
177 | off += sizeof (rec); | 252 | off += sizeof (rec); |
178 | if (off + dest[i].data_size > len) | 253 | if ( (off + dest[i].data_size > len) || |
254 | (off + dest[i].data_size < off) ) | ||
255 | { | ||
256 | GNUNET_break_op (0); | ||
179 | return GNUNET_SYSERR; | 257 | return GNUNET_SYSERR; |
258 | } | ||
180 | dest[i].data = &src[off]; | 259 | dest[i].data = &src[off]; |
181 | off += dest[i].data_size; | 260 | off += dest[i].data_size; |
261 | #if GNUNET_EXTRA_LOGGING | ||
262 | { | ||
263 | char *str; | ||
264 | |||
265 | str = GNUNET_GNSRECORD_value_to_string (dest[i].record_type, | ||
266 | dest[i].data, | ||
267 | dest[i].data_size); | ||
268 | if (NULL == str) | ||
269 | { | ||
270 | GNUNET_break_op (0); | ||
271 | return GNUNET_SYSERR; | ||
272 | } | ||
273 | GNUNET_free (str); | ||
274 | } | ||
275 | #endif | ||
182 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 276 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
183 | "Deserialized record %u with flags %d and expiration time %llu\n", | 277 | "Deserialized record %u with flags %d and expiration time %llu\n", |
184 | i, | 278 | i, |