]>
Commit | Line | Data |
---|---|---|
ca4dc4ba AZ |
1 | diff -ruN net-snmp-5.2.1.2.orig/snmplib/asn1.c net-snmp-5.2.1.2/snmplib/asn1.c |
2 | --- net-snmp-5.2.1.2.orig/snmplib/asn1.c 2004-12-10 15:07:16.000000000 +0000 | |
3 | +++ net-snmp-5.2.1.2/snmplib/asn1.c 2007-02-17 23:54:03.000000000 +0000 | |
4 | @@ -470,6 +470,13 @@ | |
5 | while (asn_length--) | |
6 | value = (value << 8) | *bufp++; | |
7 | ||
2cca4c0b | 8 | +/*#if SIZEOF_LONG != 4 |
ca4dc4ba AZ |
9 | + if ((unsigned long)value > 0xffffffff) { |
10 | + snmp_log(LOG_ERR,"truncating integer value to 32 bits\n"); | |
11 | + value &= 0xffffffff; | |
12 | + } | |
2cca4c0b | 13 | +#endif*/ |
ca4dc4ba AZ |
14 | + |
15 | DEBUGMSG(("dumpv_recv", " Integer:\t%ld (0x%.2X)\n", value, value)); | |
16 | ||
17 | *intp = value; | |
18 | @@ -535,6 +542,13 @@ | |
19 | while (asn_length--) | |
20 | value = (value << 8) | *bufp++; | |
21 | ||
22 | +#if SIZEOF_LONG != 4 | |
23 | + if (value > 0xffffffff) { | |
24 | + snmp_log(LOG_ERR,"truncating uinteger value to 32 bits\n"); | |
25 | + value &= 0xffffffff; | |
26 | + } | |
27 | +#endif | |
28 | + | |
29 | DEBUGMSG(("dumpv_recv", " UInteger:\t%ld (0x%.2X)\n", value, value)); | |
30 | ||
31 | *intp = value; | |
32 | @@ -584,6 +598,12 @@ | |
33 | return NULL; | |
34 | } | |
35 | integer = *intp; | |
36 | +#if SIZEOF_LONG != 4 | |
37 | + if ((unsigned long)integer > 0xffffffff) { | |
38 | + snmp_log(LOG_ERR,"truncating integer value to 32 bits\n"); | |
39 | + integer &= 0xffffffff; | |
40 | + } | |
41 | +#endif | |
42 | /* | |
43 | * Truncate "unnecessary" bytes off of the most significant end of this | |
44 | * 2's complement integer. There should be no sequence of 9 | |
45 | @@ -663,6 +683,12 @@ | |
46 | return NULL; | |
47 | } | |
48 | integer = *intp; | |
49 | +#if SIZEOF_LONG != 4 | |
50 | + if (integer > 0xffffffff) { | |
51 | + snmp_log(LOG_ERR,"truncating uinteger value to 32 bits\n"); | |
52 | + integer &= 0xffffffff; | |
53 | + } | |
54 | +#endif | |
55 | mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); | |
56 | /* | |
57 | * mask is 0xFF000000 on a big-endian machine | |
58 | @@ -1286,18 +1312,13 @@ | |
59 | (subidentifier << 7) + (*(u_char *) bufp & ~ASN_BIT8); | |
60 | length--; | |
61 | } while (*(u_char *) bufp++ & ASN_BIT8); /* last byte has high bit clear */ | |
62 | - /* | |
63 | - * ?? note, this test will never be true, since the largest value | |
64 | - * of subidentifier is the value of MAX_SUBID! | |
65 | - * | |
66 | - * Yes: PC-LINT says the same thing | |
67 | - * No!: the agent can be configured to use a char instead of a long | |
68 | - * for OIDs, in which case this test is essential. | |
69 | - */ | |
70 | + | |
71 | +#if defined(EIGHTBIT_SUBIDS) || (SIZEOF_LONG != 4) | |
72 | if (subidentifier > (u_long) MAX_SUBID) { | |
73 | ERROR_MSG("subidentifier too large"); | |
74 | return NULL; | |
75 | } | |
76 | +#endif | |
77 | *oidp++ = (oid) subidentifier; | |
78 | } | |
79 | ||
80 | @@ -1439,6 +1460,12 @@ | |
81 | if (i >= (int) objidlength) | |
82 | break; | |
83 | objid_val = *op++; /* XXX - doesn't handle 2.X (X > 40) */ | |
84 | +#if SIZEOF_LONG != 4 | |
85 | + if (objid_val > 0xffffffff) { | |
86 | + snmp_log(LOG_ERR,"truncating objid value to 32 bits\n"); | |
87 | + objid_val &= 0xffffffff; | |
88 | + } | |
89 | +#endif | |
90 | } | |
91 | ||
92 | /* | |
93 | @@ -1454,8 +1481,13 @@ | |
94 | */ | |
95 | for (i = 1, objid_val = first_objid_val, op = objid + 2; | |
96 | i < (int) objidlength; i++) { | |
97 | - if (i != 1) | |
98 | + if (i != 1) { | |
99 | objid_val = *op++; | |
100 | +#if SIZEOF_LONG != 4 | |
101 | + if (objid_val > 0xffffffff) /* already logged warning above */ | |
102 | + objid_val &= 0xffffffff; | |
103 | +#endif | |
104 | + } | |
105 | switch (objid_size[i]) { | |
106 | case 1: | |
107 | *data++ = (u_char) objid_val; | |
108 | @@ -1783,6 +1815,17 @@ | |
109 | low = (low << 8) | *bufp++; | |
110 | } | |
111 | ||
112 | +#if SIZEOF_LONG != 4 | |
113 | + if (high > 0xffffffff) { | |
114 | + snmp_log(LOG_ERR,"truncating counter64 high value to 32 bits\n"); | |
115 | + high &= 0xffffffff; | |
116 | + } | |
117 | + if (low > 0xffffffff) { | |
118 | + snmp_log(LOG_ERR,"truncating counter64 low value to 32 bits\n"); | |
119 | + low &= 0xffffffff; | |
120 | + } | |
121 | +#endif | |
122 | + | |
123 | cp->low = low; | |
124 | cp->high = high; | |
125 | ||
126 | @@ -1843,6 +1886,16 @@ | |
127 | intsize = 8; | |
128 | low = cp->low; | |
129 | high = cp->high; | |
130 | +#if SIZEOF_LONG != 4 | |
131 | + if (high > 0xffffffff) { | |
132 | + snmp_log(LOG_ERR,"truncating counter64 high value to 32 bits\n"); | |
133 | + high &= 0xffffffff; | |
134 | + } | |
135 | + if (low > 0xffffffff) { | |
136 | + snmp_log(LOG_ERR,"truncating counter64 low value to 32 bits\n"); | |
137 | + low &= 0xffffffff; | |
138 | + } | |
139 | +#endif | |
140 | mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); | |
141 | /* | |
142 | * mask is 0xFF000000 on a big-endian machine | |
143 | @@ -2041,6 +2094,17 @@ | |
144 | low = (low << 8) | *bufp++; | |
145 | } | |
146 | ||
147 | +#if SIZEOF_LONG != 4 | |
148 | + if (high > 0xffffffff) { | |
149 | + snmp_log(LOG_ERR,"truncating counter64 high value to 32 bits\n"); | |
150 | + high &= 0xffffffff; | |
151 | + } | |
152 | + if (low > 0xffffffff) { | |
153 | + snmp_log(LOG_ERR,"truncating counter64 low value to 32 bits\n"); | |
154 | + low &= 0xffffffff; | |
155 | + } | |
156 | +#endif | |
157 | + | |
158 | cp->low = low; | |
159 | cp->high = high; | |
160 | ||
161 | @@ -2103,6 +2167,16 @@ | |
162 | memcpy(&c64, cp, sizeof(struct counter64)); /* we're may modify it */ | |
163 | low = c64.low; | |
164 | high = c64.high; | |
165 | +#if SIZEOF_LONG != 4 | |
166 | + if (high > 0xffffffff) { | |
167 | + snmp_log(LOG_ERR,"truncating counter64 high value to 32 bits\n"); | |
168 | + high &= 0xffffffff; | |
169 | + } | |
170 | + if (low > 0xffffffff) { | |
171 | + snmp_log(LOG_ERR,"truncating counter64 low value to 32 bits\n"); | |
172 | + low &= 0xffffffff; | |
173 | + } | |
174 | +#endif | |
175 | ||
176 | /* | |
177 | * Truncate "unnecessary" bytes off of the most significant end of this | |
178 | @@ -2673,6 +2747,12 @@ | |
179 | _asn_size_err(errpre, intsize, sizeof(long)); | |
180 | return 0; | |
181 | } | |
182 | +#if SIZEOF_LONG != 4 | |
183 | + if ((unsigned long)integer > 0xffffffff) { | |
184 | + snmp_log(LOG_ERR,"truncating integer value to 32 bits\n"); | |
185 | + integer &= 0xffffffff; | |
186 | + } | |
187 | +#endif | |
188 | ||
189 | if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { | |
190 | return 0; | |
191 | @@ -2825,6 +2905,13 @@ | |
192 | return 0; | |
193 | } | |
194 | ||
195 | +#if SIZEOF_LONG != 4 | |
196 | + if (integer > 0xffffffff) { | |
197 | + snmp_log(LOG_ERR,"truncating uinteger value to 32 bits\n"); | |
198 | + integer &= 0xffffffff; | |
199 | + } | |
200 | +#endif | |
201 | + | |
202 | if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { | |
203 | return 0; | |
204 | } | |
205 | @@ -2960,6 +3047,12 @@ | |
206 | } else { | |
207 | for (i = objidlength; i > 2; i--) { | |
208 | tmpint = objid[i - 1]; | |
209 | +#if SIZEOF_LONG != 4 | |
210 | + if ((unsigned long)tmpint > 0xffffffff) { | |
211 | + snmp_log(LOG_ERR,"truncating oid subid to 32 bits\n"); | |
212 | + tmpint &= 0xffffffff; | |
213 | + } | |
214 | +#endif | |
215 | ||
216 | if (((*pkt_len - *offset) < 1) | |
217 | && !(r && asn_realloc(pkt, pkt_len))) { | |
218 | @@ -3176,6 +3269,16 @@ | |
219 | sizeof(struct counter64)); | |
220 | return 0; | |
221 | } | |
222 | +#if SIZEOF_LONG != 4 | |
223 | + if (high > 0xffffffff) { | |
224 | + snmp_log(LOG_ERR,"truncating counter64 high value to 32 bits\n"); | |
225 | + high &= 0xffffffff; | |
226 | + } | |
227 | + if (low > 0xffffffff) { | |
228 | + snmp_log(LOG_ERR,"truncating counter64 low value to 32 bits\n"); | |
229 | + low &= 0xffffffff; | |
230 | + } | |
231 | +#endif | |
232 | ||
233 | /* | |
234 | * Encode the low 4 bytes first. | |
235 | @@ -3359,6 +3462,17 @@ | |
236 | return 0; | |
237 | } | |
238 | ||
239 | +#if SIZEOF_LONG != 4 | |
240 | + if (high > 0xffffffff) { | |
241 | + snmp_log(LOG_ERR,"truncating counter64 high value to 32 bits\n"); | |
242 | + high &= 0xffffffff; | |
243 | + } | |
244 | + if (low > 0xffffffff) { | |
245 | + snmp_log(LOG_ERR,"truncating counter64 low value to 32 bits\n"); | |
246 | + low &= 0xffffffff; | |
247 | + } | |
248 | +#endif | |
249 | + | |
250 | /* | |
251 | * Encode the low 4 bytes first. | |
252 | */ | |
253 | diff -ruN net-snmp-5.2.1.2.orig/snmplib/int64.c net-snmp-5.2.1.2/snmplib/int64.c | |
254 | --- net-snmp-5.2.1.2.orig/snmplib/int64.c 2004-07-11 04:28:45.000000000 +0000 | |
255 | +++ net-snmp-5.2.1.2/snmplib/int64.c 2007-02-17 23:54:03.000000000 +0000 | |
256 | @@ -179,7 +179,9 @@ | |
257 | */ | |
258 | pu64->low = (ulT1 + u16) & 0x0FFFFFFFFL; | |
259 | pu64->high++; | |
260 | - | |
261 | +#if SIZEOF_LONG != 4 | |
262 | + pu64->high &= 0xffffffff; | |
263 | +#endif | |
264 | } /* incrByV16 */ | |
265 | ||
266 | void | |
267 | @@ -188,8 +190,15 @@ | |
268 | unsigned int tmp; | |
269 | tmp = pu64->low; | |
270 | pu64->low += u32; | |
271 | - if (pu64->low < tmp) | |
272 | +#if SIZEOF_LONG != 4 | |
273 | + pu64->low &= 0xffffffff; | |
274 | +#endif | |
275 | + if (pu64->low < tmp) { | |
276 | pu64->high++; | |
277 | +#if SIZEOF_LONG != 4 | |
278 | + pu64->high &= 0xffffffff; | |
279 | +#endif | |
280 | + } | |
281 | } | |
282 | ||
283 | /** | |
284 | @@ -214,6 +223,9 @@ | |
285 | u64Incr(U64 * pu64out, const U64 * pu64one) | |
286 | { | |
287 | pu64out->high += pu64one->high; | |
288 | +#if SIZEOF_LONG != 4 | |
289 | + pu64out->high &= 0xffffffff; | |
290 | +#endif | |
291 | incrByU32(pu64out, pu64one->low); | |
292 | } | |
293 | ||
294 | @@ -247,7 +259,6 @@ | |
295 | void | |
296 | zeroU64(U64 * pu64) | |
297 | { | |
298 | - | |
299 | pu64->low = 0; | |
300 | pu64->high = 0; | |
301 | } /* zeroU64 */ | |
302 | @@ -315,8 +326,12 @@ | |
303 | */ | |
304 | if (new_val->high == old_val->high) { | |
305 | DEBUGMSGTL(("c64:check_wrap", "32 bit wrap\n")); | |
306 | - if (adjust) | |
307 | + if (adjust) { | |
308 | ++new_val->high; | |
309 | +#if SIZEOF_LONG != 4 | |
310 | + new_val->high &= 0xffffffff; | |
311 | +#endif | |
312 | + } | |
313 | return 32; | |
314 | } | |
315 | else if ((new_val->high == (old_val->high + 1)) || | |
316 | diff -ruN net-snmp-5.2.1.2.orig/snmplib/snmp_client.c net-snmp-5.2.1.2/snmplib/snmp_client.c | |
317 | --- net-snmp-5.2.1.2.orig/snmplib/snmp_client.c 2004-12-10 02:21:38.000000000 +0000 | |
318 | +++ net-snmp-5.2.1.2/snmplib/snmp_client.c 2007-02-17 23:54:43.000000000 +0000 | |
319 | @@ -94,6 +94,7 @@ | |
320 | ||
321 | #include <net-snmp/library/snmp_api.h> | |
322 | #include <net-snmp/library/snmp_client.h> | |
323 | +#include <net-snmp/library/snmp_logging.h> | |
324 | #include <net-snmp/library/snmp_secmod.h> | |
325 | #include <net-snmp/library/mib.h> | |
326 | ||
327 | @@ -714,41 +715,193 @@ | |
328 | */ | |
329 | ||
330 | int | |
331 | -snmp_set_var_value(netsnmp_variable_list * newvar, | |
332 | - const u_char * val_str, size_t val_len) | |
333 | +snmp_set_var_value(netsnmp_variable_list * vars, | |
334 | + const u_char * value, size_t len) | |
335 | { | |
336 | + int largeval = 1; | |
337 | + | |
338 | /* | |
339 | * xxx-rks: why the unconditional free? why not use existing | |
340 | - * memory, if val_len < newvar->val_len ? | |
341 | + * memory, if len < vars->val_len ? | |
342 | */ | |
343 | - if (newvar->val.string && newvar->val.string != newvar->buf) { | |
344 | - free(newvar->val.string); | |
345 | + if (vars->val.string && vars->val.string != vars->buf) { | |
346 | + free(vars->val.string); | |
347 | } | |
348 | - | |
349 | - newvar->val.string = 0; | |
350 | - newvar->val_len = 0; | |
351 | + vars->val.string = 0; | |
352 | + vars->val_len = 0; | |
353 | ||
354 | /* | |
355 | - * need a pointer and a length to copy a string value. | |
356 | + * use built-in storage for smaller values | |
357 | */ | |
358 | - if (val_str && val_len) { | |
359 | - if (val_len <= sizeof(newvar->buf)) | |
360 | - newvar->val.string = newvar->buf; | |
361 | - else { | |
362 | - newvar->val.string = (u_char *) malloc(val_len); | |
363 | - if (!newvar->val.string) | |
364 | - return 1; | |
365 | - } | |
366 | - memmove(newvar->val.string, val_str, val_len); | |
367 | - newvar->val_len = val_len; | |
368 | - } else if (val_str) { | |
369 | + if (len <= (sizeof(vars->buf) - 1)) { | |
370 | + vars->val.string = (u_char *) vars->buf; | |
371 | + largeval = 0; | |
372 | + } | |
373 | + | |
374 | + if ((0 == len) || (NULL == value)) { | |
375 | + vars->val.string[0] = 0; | |
376 | + return 0; | |
377 | + } | |
378 | + | |
379 | + vars->val_len = len; | |
380 | + switch (vars->type) { | |
381 | + case ASN_INTEGER: | |
382 | + case ASN_UNSIGNED: | |
383 | + case ASN_TIMETICKS: | |
384 | + case ASN_IPADDRESS: | |
385 | + case ASN_COUNTER: | |
386 | + if (value) { | |
387 | + if (vars->val_len == sizeof(int)) { | |
388 | + if (ASN_INTEGER == vars->type) { | |
389 | + const int *val_int | |
390 | + = (const int *) value; | |
391 | + *(vars->val.integer) = (long) *val_int; | |
392 | + } else { | |
393 | + const u_int *val_uint | |
394 | + = (const u_int *) value; | |
395 | + *(vars->val.integer) = (unsigned long) *val_uint; | |
396 | + } | |
397 | + } | |
398 | +#if SIZEOF_LONG != SIZEOF_INT | |
399 | + else if (vars->val_len == sizeof(long)){ | |
400 | + const u_long *val_ulong | |
401 | + = (const u_long *) value; | |
402 | + *(vars->val.integer) = *val_ulong; | |
403 | + if (*(vars->val.integer) > 0xffffffff) { | |
404 | + snmp_log(LOG_ERR,"truncating integer value > 32 bits\n"); | |
405 | + *(vars->val.integer) &= 0xffffffff; | |
406 | + } | |
407 | + } | |
408 | +#endif | |
409 | +#if SIZEOF_LONG != SIZEOF_LONG_LONG | |
410 | + else if (vars->val_len == sizeof(long long)){ | |
411 | + const unsigned long long *val_ullong | |
412 | + = (const unsigned long long *) value; | |
413 | + *(vars->val.integer) = (long) *val_ullong; | |
414 | + if (*(vars->val.integer) > 0xffffffff) { | |
415 | + snmp_log(LOG_ERR,"truncating integer value > 32 bits\n"); | |
416 | + *(vars->val.integer) &= 0xffffffff; | |
417 | + } | |
418 | + } | |
419 | +#endif | |
420 | +#if SIZEOF_SHORT != SIZEOF_INT | |
421 | + else if (vars->val_len == sizeof(short)) { | |
422 | + if (ASN_INTEGER == vars->type) { | |
423 | + const short *val_short | |
424 | + = (const short *) value; | |
425 | + *(vars->val.integer) = (long) *val_short; | |
426 | + } else { | |
427 | + const u_short *val_ushort | |
428 | + = (const u_short *) value; | |
429 | + *(vars->val.integer) = (unsigned long) *val_ushort; | |
430 | + } | |
431 | + } | |
432 | +#endif | |
433 | + else if (vars->val_len == sizeof(char)) { | |
434 | + if (ASN_INTEGER == vars->type) { | |
435 | + const char *val_char | |
436 | + = (const char *) value; | |
437 | + *(vars->val.integer) = (long) *val_char; | |
438 | + } else { | |
439 | + *(vars->val.integer) = (unsigned long) *value; | |
440 | + } | |
441 | + } | |
442 | + else { | |
443 | + snmp_log(LOG_ERR,"bad size for integer-like type (%d)\n", | |
444 | + vars->val_len); | |
445 | + return (1); | |
446 | + } | |
447 | + } else | |
448 | + *(vars->val.integer) = 0; | |
449 | + vars->val_len = sizeof(long); | |
450 | + break; | |
451 | + | |
452 | + case ASN_OBJECT_ID: | |
453 | + case ASN_PRIV_IMPLIED_OBJECT_ID: | |
454 | + case ASN_PRIV_INCL_RANGE: | |
455 | + case ASN_PRIV_EXCL_RANGE: | |
456 | + if (largeval) { | |
457 | + vars->val.objid = (oid *) malloc(vars->val_len); | |
458 | + } | |
459 | + if (vars->val.objid == NULL) { | |
460 | + snmp_log(LOG_ERR,"no storage for OID\n"); | |
461 | + return 1; | |
462 | + } | |
463 | + memmove(vars->val.objid, value, vars->val_len); | |
464 | + break; | |
465 | + | |
466 | + case ASN_PRIV_IMPLIED_OCTET_STR: | |
467 | + case ASN_OCTET_STR: | |
468 | + case ASN_BIT_STR: | |
469 | + case ASN_OPAQUE: | |
470 | + case ASN_NSAP: | |
471 | + if (largeval) { | |
472 | + vars->val.string = (u_char *) malloc(vars->val_len + 1); | |
473 | + } | |
474 | + if (vars->val.string == NULL) { | |
475 | + snmp_log(LOG_ERR,"no storage for OID\n"); | |
476 | + return 1; | |
477 | + } | |
478 | + memmove(vars->val.string, value, vars->val_len); | |
479 | /* | |
480 | - * NULL STRING != NULL ptr | |
481 | + * Make sure the string is zero-terminated; some bits of code make | |
482 | + * this assumption. Easier to do this here than fix all these wrong | |
483 | + * assumptions. | |
484 | */ | |
485 | - newvar->val.string = newvar->buf; | |
486 | - newvar->val.string[0] = '\0'; | |
487 | - newvar->val_len = 0; | |
488 | + vars->val.string[vars->val_len] = '\0'; | |
489 | + break; | |
490 | + | |
491 | + case SNMP_NOSUCHOBJECT: | |
492 | + case SNMP_NOSUCHINSTANCE: | |
493 | + case SNMP_ENDOFMIBVIEW: | |
494 | + case ASN_NULL: | |
495 | + vars->val_len = 0; | |
496 | + vars->val.string = NULL; | |
497 | + break; | |
498 | + | |
499 | +#ifdef OPAQUE_SPECIAL_TYPES | |
500 | + case ASN_OPAQUE_U64: | |
501 | + case ASN_OPAQUE_I64: | |
502 | +#endif /* OPAQUE_SPECIAL_TYPES */ | |
503 | + case ASN_COUNTER64: | |
504 | + if (largeval) { | |
505 | + snmp_log(LOG_ERR,"bad size for counter 64 (%d)\n", | |
506 | + vars->val_len); | |
507 | + return (1); | |
508 | + } | |
509 | + vars->val_len = sizeof(struct counter64); | |
510 | + memmove(vars->val.counter64, value, vars->val_len); | |
511 | + break; | |
512 | + | |
513 | +#ifdef OPAQUE_SPECIAL_TYPES | |
514 | + case ASN_OPAQUE_FLOAT: | |
515 | + if (largeval) { | |
516 | + snmp_log(LOG_ERR,"bad size for opaque float (%d)\n", | |
517 | + vars->val_len); | |
518 | + return (1); | |
519 | + } | |
520 | + vars->val_len = sizeof(float); | |
521 | + memmove(vars->val.floatVal, value, vars->val_len); | |
522 | + break; | |
523 | + | |
524 | + case ASN_OPAQUE_DOUBLE: | |
525 | + if (largeval) { | |
526 | + snmp_log(LOG_ERR,"bad size for opaque double (%d)\n", | |
527 | + vars->val_len); | |
528 | + return (1); | |
529 | + } | |
530 | + vars->val_len = sizeof(double); | |
531 | + memmove(vars->val.doubleVal, value, vars->val_len); | |
532 | + break; | |
533 | + | |
534 | +#endif /* OPAQUE_SPECIAL_TYPES */ | |
535 | + | |
536 | + default: | |
537 | + snmp_log(LOG_ERR,"no storage for OID\n"); | |
538 | + snmp_set_detail("Internal error in type switching\n"); | |
539 | + return (1); | |
540 | } | |
541 | + | |
542 | return 0; | |
543 | } | |
544 |