File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/xmlrpc_data.c |
Location: | line 100, column 5 |
Description: | Access to field '_refcount' results in a dereference of a null pointer (loaded from variable 'valueP') |
1 | /* Copyright information is at end of file */ | |||||
2 | ||||||
3 | #include "xmlrpc_config.h" | |||||
4 | ||||||
5 | #include <stddef.h> | |||||
6 | #include <stdlib.h> | |||||
7 | #include <stdarg.h> | |||||
8 | #include <string.h> | |||||
9 | ||||||
10 | #include "bool.h" | |||||
11 | #include "mallocvar.h" | |||||
12 | ||||||
13 | #include "xmlrpc-c/base.h" | |||||
14 | #include "xmlrpc-c/base_int.h" | |||||
15 | ||||||
16 | ||||||
17 | ||||||
18 | static void | |||||
19 | destroyCptr(xmlrpc_value * const valueP) { | |||||
20 | ||||||
21 | if (valueP->_value.cptr.dtor) | |||||
22 | valueP->_value.cptr.dtor(valueP->_value.cptr.dtorContext, | |||||
23 | valueP->_value.cptr.objectP); | |||||
24 | } | |||||
25 | ||||||
26 | ||||||
27 | ||||||
28 | static void | |||||
29 | destroyValue(xmlrpc_value * const valueP) { | |||||
30 | ||||||
31 | /* First, we need to destroy this value's contents, if any. */ | |||||
32 | switch (valueP->_type) { | |||||
33 | case XMLRPC_TYPE_INT: | |||||
34 | break; | |||||
35 | ||||||
36 | case XMLRPC_TYPE_BOOL: | |||||
37 | break; | |||||
38 | ||||||
39 | case XMLRPC_TYPE_DOUBLE: | |||||
40 | break; | |||||
41 | ||||||
42 | case XMLRPC_TYPE_DATETIME: | |||||
43 | xmlrpc_destroyDatetime(valueP); | |||||
44 | break; | |||||
45 | ||||||
46 | case XMLRPC_TYPE_STRING: | |||||
47 | xmlrpc_destroyString(valueP); | |||||
48 | break; | |||||
49 | ||||||
50 | case XMLRPC_TYPE_BASE64: | |||||
51 | xmlrpc_mem_block_clean(&valueP->_block); | |||||
52 | break; | |||||
53 | ||||||
54 | case XMLRPC_TYPE_ARRAY: | |||||
55 | xmlrpc_destroyArrayContents(valueP); | |||||
56 | break; | |||||
57 | ||||||
58 | case XMLRPC_TYPE_STRUCT: | |||||
59 | xmlrpc_destroyStruct(valueP); | |||||
60 | break; | |||||
61 | ||||||
62 | case XMLRPC_TYPE_C_PTR: | |||||
63 | destroyCptr(valueP); | |||||
64 | break; | |||||
65 | ||||||
66 | case XMLRPC_TYPE_NIL: | |||||
67 | break; | |||||
68 | ||||||
69 | case XMLRPC_TYPE_I8: | |||||
70 | break; | |||||
71 | ||||||
72 | case XMLRPC_TYPE_DEAD: | |||||
73 | XMLRPC_ASSERT(false)do if (!(false)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_data.c" , 73); while (0); /* Can't happen, per entry conditions */ | |||||
74 | ||||||
75 | default: | |||||
76 | XMLRPC_ASSERT(false)do if (!(false)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_data.c" , 76); while (0); /* There are no other possible values */ | |||||
77 | } | |||||
78 | ||||||
79 | /* Next, we mark this value as invalid, to help catch refcount | |||||
80 | ** errors. */ | |||||
81 | valueP->_type = XMLRPC_TYPE_DEAD; | |||||
82 | ||||||
83 | /* Finally, we destroy the value itself. */ | |||||
84 | free(valueP); | |||||
85 | } | |||||
86 | ||||||
87 | ||||||
88 | ||||||
89 | /*========================================================================= | |||||
90 | ** Reference Counting | |||||
91 | **========================================================================= | |||||
92 | ** Some simple reference-counting code. The xmlrpc_DECREF routine is in | |||||
93 | ** charge of destroying values when their reference count equals zero. | |||||
94 | */ | |||||
95 | ||||||
96 | void | |||||
97 | xmlrpc_INCREF (xmlrpc_value * const valueP) { | |||||
98 | ||||||
99 | XMLRPC_ASSERT_VALUE_OK(valueP)do if (!((valueP) != ((void*)0) && (valueP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_data.c" , 99); while (0); | |||||
| ||||||
100 | XMLRPC_ASSERT(valueP->_refcount > 0)do if (!(valueP->_refcount > 0)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_data.c", 100); while ( 0); | |||||
| ||||||
101 | ||||||
102 | ++valueP->_refcount; | |||||
103 | } | |||||
104 | ||||||
105 | ||||||
106 | ||||||
107 | void | |||||
108 | xmlrpc_DECREF (xmlrpc_value * const valueP) { | |||||
109 | ||||||
110 | XMLRPC_ASSERT_VALUE_OK(valueP)do if (!((valueP) != ((void*)0) && (valueP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_data.c" , 110); while (0); | |||||
111 | XMLRPC_ASSERT(valueP->_refcount > 0)do if (!(valueP->_refcount > 0)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_data.c", 111); while ( 0); | |||||
112 | XMLRPC_ASSERT(valueP->_type != XMLRPC_TYPE_DEAD)do if (!(valueP->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_data.c", 112); while ( 0); | |||||
113 | ||||||
114 | valueP->_refcount--; | |||||
115 | ||||||
116 | /* If we have no more refs, we need to deallocate this value. */ | |||||
117 | if (valueP->_refcount == 0) | |||||
118 | destroyValue(valueP); | |||||
119 | } | |||||
120 | ||||||
121 | ||||||
122 | ||||||
123 | /*========================================================================= | |||||
124 | Utiltiies | |||||
125 | =========================================================================*/ | |||||
126 | ||||||
127 | const char * | |||||
128 | xmlrpc_type_name(xmlrpc_type const type) { | |||||
129 | ||||||
130 | switch (type) { | |||||
131 | ||||||
132 | case XMLRPC_TYPE_INT: return "INT"; | |||||
133 | case XMLRPC_TYPE_BOOL: return "BOOL"; | |||||
134 | case XMLRPC_TYPE_DOUBLE: return "DOUBLE"; | |||||
135 | case XMLRPC_TYPE_DATETIME: return "DATETIME"; | |||||
136 | case XMLRPC_TYPE_STRING: return "STRING"; | |||||
137 | case XMLRPC_TYPE_BASE64: return "BASE64"; | |||||
138 | case XMLRPC_TYPE_ARRAY: return "ARRAY"; | |||||
139 | case XMLRPC_TYPE_STRUCT: return "STRUCT"; | |||||
140 | case XMLRPC_TYPE_C_PTR: return "C_PTR"; | |||||
141 | case XMLRPC_TYPE_NIL: return "NIL"; | |||||
142 | case XMLRPC_TYPE_I8: return "I8"; | |||||
143 | case XMLRPC_TYPE_DEAD: return "DEAD"; | |||||
144 | default: return "???"; | |||||
145 | ||||||
146 | } | |||||
147 | } | |||||
148 | ||||||
149 | ||||||
150 | ||||||
151 | static void | |||||
152 | validateType(xmlrpc_env * const envP, | |||||
153 | const xmlrpc_value * const valueP, | |||||
154 | xmlrpc_type const expectedType) { | |||||
155 | ||||||
156 | if (valueP->_type != expectedType) { | |||||
157 | xmlrpc_env_set_fault_formatted( | |||||
158 | envP, XMLRPC_TYPE_ERROR(-501), "Value of type %s supplied where " | |||||
159 | "type %s was expected.", | |||||
160 | xmlrpc_type_name(valueP->_type), xmlrpc_type_name(expectedType)); | |||||
161 | } | |||||
162 | } | |||||
163 | ||||||
164 | ||||||
165 | ||||||
166 | /*========================================================================= | |||||
167 | Extracting XML-RPC value | |||||
168 | =========================================================================== | |||||
169 | These routines extract XML-RPC values into ordinary C data types. | |||||
170 | ||||||
171 | For array and struct values, see the separates files xmlrpc_array.c | |||||
172 | and xmlrpc_struct.c. | |||||
173 | =========================================================================*/ | |||||
174 | ||||||
175 | void | |||||
176 | xmlrpc_read_int(xmlrpc_env * const envP, | |||||
177 | const xmlrpc_value * const valueP, | |||||
178 | xmlrpc_int32 * const intValueP) { | |||||
179 | ||||||
180 | validateType(envP, valueP, XMLRPC_TYPE_INT); | |||||
181 | if (!envP->fault_occurred) | |||||
182 | *intValueP = valueP->_value.i; | |||||
183 | } | |||||
184 | ||||||
185 | ||||||
186 | ||||||
187 | void | |||||
188 | xmlrpc_read_bool(xmlrpc_env * const envP, | |||||
189 | const xmlrpc_value * const valueP, | |||||
190 | xmlrpc_bool * const boolValueP) { | |||||
191 | ||||||
192 | validateType(envP, valueP, XMLRPC_TYPE_BOOL); | |||||
193 | if (!envP->fault_occurred) | |||||
194 | *boolValueP = valueP->_value.b; | |||||
195 | } | |||||
196 | ||||||
197 | ||||||
198 | ||||||
199 | void | |||||
200 | xmlrpc_read_double(xmlrpc_env * const envP, | |||||
201 | const xmlrpc_value * const valueP, | |||||
202 | xmlrpc_double * const doubleValueP) { | |||||
203 | ||||||
204 | validateType(envP, valueP, XMLRPC_TYPE_DOUBLE); | |||||
205 | if (!envP->fault_occurred) | |||||
206 | *doubleValueP = valueP->_value.d; | |||||
207 | ||||||
208 | } | |||||
209 | ||||||
210 | ||||||
211 | ||||||
212 | /* datetime stuff is in xmlrpc_datetime.c */ | |||||
213 | ||||||
214 | /* string stuff is in xmlrpc_string.c */ | |||||
215 | ||||||
216 | ||||||
217 | ||||||
218 | void | |||||
219 | xmlrpc_read_base64(xmlrpc_env * const envP, | |||||
220 | const xmlrpc_value * const valueP, | |||||
221 | size_t * const lengthP, | |||||
222 | const unsigned char ** const byteStringValueP) { | |||||
223 | ||||||
224 | validateType(envP, valueP, XMLRPC_TYPE_BASE64); | |||||
225 | if (!envP->fault_occurred) { | |||||
226 | size_t const size = | |||||
227 | XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block)(xmlrpc_mem_block_size(&valueP->_block) / sizeof(char) ); | |||||
228 | const char * const contents = | |||||
229 | XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block)((char*) xmlrpc_mem_block_contents(&valueP->_block)); | |||||
230 | ||||||
231 | char * byteStringValue; | |||||
232 | ||||||
233 | byteStringValue = malloc(size); | |||||
234 | if (byteStringValue == NULL((void*)0)) | |||||
235 | xmlrpc_faultf(envP, | |||||
236 | "Unable to allocate %u bytes for byte string.", | |||||
237 | (unsigned)size); | |||||
238 | else { | |||||
239 | memcpy(byteStringValue, contents, size); | |||||
240 | *byteStringValueP = (const unsigned char *)byteStringValue; | |||||
241 | *lengthP = size; | |||||
242 | } | |||||
243 | } | |||||
244 | } | |||||
245 | ||||||
246 | ||||||
247 | ||||||
248 | void | |||||
249 | xmlrpc_read_base64_old(xmlrpc_env * const envP, | |||||
250 | const xmlrpc_value * const valueP, | |||||
251 | size_t * const lengthP, | |||||
252 | const unsigned char ** const byteStringValueP) { | |||||
253 | ||||||
254 | validateType(envP, valueP, XMLRPC_TYPE_BASE64); | |||||
255 | if (!envP->fault_occurred) { | |||||
256 | *lengthP = | |||||
257 | XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block)(xmlrpc_mem_block_size(&valueP->_block) / sizeof(char) ); | |||||
258 | *byteStringValueP = (const unsigned char *) | |||||
259 | XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block)((char*) xmlrpc_mem_block_contents(&valueP->_block)); | |||||
260 | } | |||||
261 | } | |||||
262 | ||||||
263 | ||||||
264 | ||||||
265 | void | |||||
266 | xmlrpc_read_base64_size(xmlrpc_env * const envP, | |||||
267 | const xmlrpc_value * const valueP, | |||||
268 | size_t * const lengthP) { | |||||
269 | ||||||
270 | validateType(envP, valueP, XMLRPC_TYPE_BASE64); | |||||
271 | if (!envP->fault_occurred) | |||||
272 | *lengthP = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block)(xmlrpc_mem_block_size(&valueP->_block) / sizeof(char) ); | |||||
273 | } | |||||
274 | ||||||
275 | ||||||
276 | ||||||
277 | void | |||||
278 | xmlrpc_read_cptr(xmlrpc_env * const envP, | |||||
279 | const xmlrpc_value * const valueP, | |||||
280 | void ** const ptrValueP) { | |||||
281 | ||||||
282 | validateType(envP, valueP, XMLRPC_TYPE_C_PTR); | |||||
283 | if (!envP->fault_occurred) | |||||
284 | *ptrValueP = valueP->_value.cptr.objectP; | |||||
285 | } | |||||
286 | ||||||
287 | ||||||
288 | ||||||
289 | void | |||||
290 | xmlrpc_read_nil(xmlrpc_env * const envP, | |||||
291 | xmlrpc_value * const valueP) { | |||||
292 | /*---------------------------------------------------------------------------- | |||||
293 | Read out the value of a nil value. It doesn't have one, of course, so | |||||
294 | this is essentially a no-op. But it does validate the type and is | |||||
295 | necessary to match all the other types. | |||||
296 | -----------------------------------------------------------------------------*/ | |||||
297 | validateType(envP, valueP, XMLRPC_TYPE_NIL); | |||||
298 | } | |||||
299 | ||||||
300 | ||||||
301 | ||||||
302 | void | |||||
303 | xmlrpc_read_i8(xmlrpc_env * const envP, | |||||
304 | const xmlrpc_value * const valueP, | |||||
305 | xmlrpc_int64 * const intValueP) { | |||||
306 | ||||||
307 | validateType(envP, valueP, XMLRPC_TYPE_I8); | |||||
308 | if (!envP->fault_occurred) | |||||
309 | *intValueP = valueP->_value.i8; | |||||
310 | } | |||||
311 | ||||||
312 | ||||||
313 | ||||||
314 | xmlrpc_type xmlrpc_value_type (xmlrpc_value* const value) | |||||
315 | { | |||||
316 | XMLRPC_ASSERT_VALUE_OK(value)do if (!((value) != ((void*)0) && (value)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_data.c" , 316); while (0); | |||||
317 | return value->_type; | |||||
318 | } | |||||
319 | ||||||
320 | ||||||
321 | ||||||
322 | void | |||||
323 | xmlrpc_createXmlrpcValue(xmlrpc_env * const envP, | |||||
324 | xmlrpc_value ** const valPP) { | |||||
325 | /*---------------------------------------------------------------------------- | |||||
326 | Create a blank xmlrpc_value to be filled in. | |||||
327 | ||||||
328 | Set the reference count to 1. | |||||
329 | -----------------------------------------------------------------------------*/ | |||||
330 | xmlrpc_value * valP; | |||||
331 | ||||||
332 | MALLOCVAR(valP)valP = malloc(sizeof(*valP)); | |||||
333 | if (!valP) | |||||
334 | xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR(-500), | |||||
335 | "Could not allocate memory for xmlrpc_value"); | |||||
336 | else | |||||
337 | valP->_refcount = 1; | |||||
338 | ||||||
339 | *valPP = valP; | |||||
340 | } | |||||
341 | ||||||
342 | ||||||
343 | ||||||
344 | xmlrpc_value * | |||||
345 | xmlrpc_int_new(xmlrpc_env * const envP, | |||||
346 | xmlrpc_int32 const value) { | |||||
347 | ||||||
348 | xmlrpc_value * valP; | |||||
349 | ||||||
350 | xmlrpc_createXmlrpcValue(envP, &valP); | |||||
351 | ||||||
352 | if (!envP->fault_occurred) { | |||||
353 | valP->_type = XMLRPC_TYPE_INT; | |||||
354 | valP->_value.i = value; | |||||
355 | } | |||||
356 | return valP; | |||||
357 | } | |||||
358 | ||||||
359 | ||||||
360 | ||||||
361 | xmlrpc_value * | |||||
362 | xmlrpc_i8_new(xmlrpc_env * const envP, | |||||
363 | xmlrpc_int64 const value) { | |||||
364 | ||||||
365 | xmlrpc_value * valP; | |||||
366 | ||||||
367 | xmlrpc_createXmlrpcValue(envP, &valP); | |||||
368 | ||||||
369 | if (!envP->fault_occurred) { | |||||
370 | valP->_type = XMLRPC_TYPE_I8; | |||||
371 | valP->_value.i8 = value; | |||||
372 | } | |||||
373 | return valP; | |||||
374 | } | |||||
375 | ||||||
376 | ||||||
377 | ||||||
378 | xmlrpc_value * | |||||
379 | xmlrpc_bool_new(xmlrpc_env * const envP, | |||||
380 | xmlrpc_bool const value) { | |||||
381 | ||||||
382 | xmlrpc_value * valP; | |||||
383 | ||||||
384 | xmlrpc_createXmlrpcValue(envP, &valP); | |||||
385 | ||||||
386 | if (!envP->fault_occurred) { | |||||
387 | valP->_type = XMLRPC_TYPE_BOOL; | |||||
388 | valP->_value.b = value; | |||||
389 | } | |||||
390 | return valP; | |||||
391 | } | |||||
392 | ||||||
393 | ||||||
394 | ||||||
395 | xmlrpc_value * | |||||
396 | xmlrpc_double_new(xmlrpc_env * const envP, | |||||
397 | double const value) { | |||||
398 | ||||||
399 | xmlrpc_value * valP; | |||||
400 | ||||||
401 | xmlrpc_createXmlrpcValue(envP, &valP); | |||||
402 | ||||||
403 | if (!envP->fault_occurred) { | |||||
404 | valP->_type = XMLRPC_TYPE_DOUBLE; | |||||
405 | valP->_value.d = value; | |||||
406 | } | |||||
407 | return valP; | |||||
408 | } | |||||
409 | ||||||
410 | ||||||
411 | ||||||
412 | xmlrpc_value * | |||||
413 | xmlrpc_base64_new(xmlrpc_env * const envP, | |||||
414 | size_t const length, | |||||
415 | const unsigned char * const value) { | |||||
416 | ||||||
417 | xmlrpc_value * valP; | |||||
418 | ||||||
419 | xmlrpc_createXmlrpcValue(envP, &valP); | |||||
420 | ||||||
421 | if (!envP->fault_occurred) { | |||||
422 | valP->_type = XMLRPC_TYPE_BASE64; | |||||
423 | ||||||
424 | xmlrpc_mem_block_init(envP, &valP->_block, length); | |||||
425 | if (!envP->fault_occurred) { | |||||
426 | char * const contents = | |||||
427 | xmlrpc_mem_block_contents(&valP->_block); | |||||
428 | memcpy(contents, value, length); | |||||
429 | } | |||||
430 | if (envP->fault_occurred) | |||||
431 | free(valP); | |||||
432 | } | |||||
433 | return valP; | |||||
434 | } | |||||
435 | ||||||
436 | ||||||
437 | ||||||
438 | /* array stuff is in xmlrpc_array.c */ | |||||
439 | ||||||
440 | ||||||
441 | ||||||
442 | xmlrpc_value * | |||||
443 | xmlrpc_cptr_new(xmlrpc_env * const envP, | |||||
444 | void * const value) { | |||||
445 | ||||||
446 | return xmlrpc_cptr_new_dtor(envP, value, NULL((void*)0), NULL((void*)0)); | |||||
447 | } | |||||
448 | ||||||
449 | ||||||
450 | ||||||
451 | xmlrpc_value * | |||||
452 | xmlrpc_cptr_new_dtor(xmlrpc_env * const envP, | |||||
453 | void * const value, | |||||
454 | xmlrpc_cptr_dtor_fn const dtor, | |||||
455 | void * const dtorContext) { | |||||
456 | ||||||
457 | xmlrpc_value * valP; | |||||
458 | ||||||
459 | xmlrpc_createXmlrpcValue(envP, &valP); | |||||
460 | ||||||
461 | if (!envP->fault_occurred) { | |||||
462 | valP->_type = XMLRPC_TYPE_C_PTR; | |||||
463 | valP->_value.cptr.objectP = value; | |||||
464 | valP->_value.cptr.dtor = dtor; | |||||
465 | valP->_value.cptr.dtorContext = dtorContext; | |||||
466 | } | |||||
467 | return valP; | |||||
468 | } | |||||
469 | ||||||
470 | ||||||
471 | ||||||
472 | xmlrpc_value * | |||||
473 | xmlrpc_nil_new(xmlrpc_env * const envP) { | |||||
474 | xmlrpc_value * valP; | |||||
475 | ||||||
476 | xmlrpc_createXmlrpcValue(envP, &valP); | |||||
477 | if (!envP->fault_occurred) | |||||
478 | valP->_type = XMLRPC_TYPE_NIL; | |||||
479 | ||||||
480 | return valP; | |||||
481 | } | |||||
482 | ||||||
483 | ||||||
484 | ||||||
485 | /* Copyright (C) 2001 by First Peer, Inc. All rights reserved. | |||||
486 | ** Copyright (C) 2001 by Eric Kidd. All rights reserved. | |||||
487 | ** | |||||
488 | ** Redistribution and use in source and binary forms, with or without | |||||
489 | ** modification, are permitted provided that the following conditions | |||||
490 | ** are met: | |||||
491 | ** 1. Redistributions of source code must retain the above copyright | |||||
492 | ** notice, this list of conditions and the following disclaimer. | |||||
493 | ** 2. Redistributions in binary form must reproduce the above copyright | |||||
494 | ** notice, this list of conditions and the following disclaimer in the | |||||
495 | ** documentation and/or other materials provided with the distribution. | |||||
496 | ** 3. The name of the author may not be used to endorse or promote products | |||||
497 | ** derived from this software without specific prior written permission. | |||||
498 | ** | |||||
499 | ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||||
500 | ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
501 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
502 | ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||||
503 | ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||||
504 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||||
505 | ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
506 | ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||||
507 | ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||||
508 | ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
509 | ** SUCH DAMAGE. */ |