File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/xmlrpc_struct.c |
Location: | line 208, column 9 |
Description: | Access to field 'fault_occurred' results in a dereference of a null pointer (loaded from variable 'envP') |
1 | #include "xmlrpc_config.h" | |||||
2 | ||||||
3 | #include <assert.h> | |||||
4 | #include <stddef.h> | |||||
5 | #include <stdlib.h> | |||||
6 | #include <string.h> | |||||
7 | ||||||
8 | #include "xmlrpc-c/base.h" | |||||
9 | #include "xmlrpc-c/base_int.h" | |||||
10 | #include "int.h" | |||||
11 | ||||||
12 | #define KEY_ERROR_BUFFER_SZ(32) (32) | |||||
13 | ||||||
14 | ||||||
15 | void | |||||
16 | xmlrpc_destroyStruct(xmlrpc_value * const structP) { | |||||
17 | ||||||
18 | _struct_member * const members = | |||||
19 | XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block)((_struct_member*) xmlrpc_mem_block_contents(&structP-> _block)); | |||||
20 | size_t const size = | |||||
21 | XMLRPC_MEMBLOCK_SIZE(_struct_member, &structP->_block)(xmlrpc_mem_block_size(&structP->_block) / sizeof(_struct_member )); | |||||
22 | ||||||
23 | unsigned int i; | |||||
24 | ||||||
25 | for (i = 0; i < size; ++i) { | |||||
26 | xmlrpc_DECREF(members[i].key); | |||||
27 | xmlrpc_DECREF(members[i].value); | |||||
28 | } | |||||
29 | XMLRPC_MEMBLOCK_CLEAN(_struct_member, &structP->_block)xmlrpc_mem_block_clean(&structP->_block); | |||||
30 | } | |||||
31 | ||||||
32 | ||||||
33 | ||||||
34 | /*========================================================================= | |||||
35 | ** xmlrpc_struct_new | |||||
36 | **========================================================================= | |||||
37 | ** Create a new <struct> value. The corresponding destructor code | |||||
38 | ** currently lives in xmlrpc_DECREF. | |||||
39 | ** | |||||
40 | ** We store the individual members in an array of _struct_member. This | |||||
41 | ** contains a key, a hash code, and a value. We look up keys by doing | |||||
42 | ** a linear search of the hash codes. | |||||
43 | */ | |||||
44 | ||||||
45 | xmlrpc_value * | |||||
46 | xmlrpc_struct_new(xmlrpc_env * const envP) { | |||||
47 | ||||||
48 | xmlrpc_value * valP; | |||||
49 | ||||||
50 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c", 50); while ( 0); | |||||
51 | ||||||
52 | xmlrpc_createXmlrpcValue(envP, &valP); | |||||
53 | if (!envP->fault_occurred) { | |||||
54 | valP->_type = XMLRPC_TYPE_STRUCT; | |||||
55 | ||||||
56 | XMLRPC_MEMBLOCK_INIT(_struct_member, envP, &valP->_block, 0)xmlrpc_mem_block_init((envP), (&valP->_block), sizeof( _struct_member) * (0)); | |||||
57 | ||||||
58 | if (envP->fault_occurred) | |||||
59 | free(valP); | |||||
60 | } | |||||
61 | return valP; | |||||
62 | } | |||||
63 | ||||||
64 | ||||||
65 | ||||||
66 | /*========================================================================= | |||||
67 | ** xmlrpc_struct_size | |||||
68 | **========================================================================= | |||||
69 | ** Return the number of key-value pairs contained in the struct. If the | |||||
70 | ** value is not a struct, return -1 and set a fault. | |||||
71 | */ | |||||
72 | ||||||
73 | int | |||||
74 | xmlrpc_struct_size(xmlrpc_env * const envP, | |||||
75 | xmlrpc_value * const structP) { | |||||
76 | ||||||
77 | int retval; | |||||
78 | ||||||
79 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c", 79); while ( 0); | |||||
80 | XMLRPC_ASSERT_VALUE_OK(structP)do if (!((structP) != ((void*)0) && (structP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 80); while (0); | |||||
81 | ||||||
82 | if (structP->_type != XMLRPC_TYPE_STRUCT) { | |||||
83 | xmlrpc_env_set_fault_formatted( | |||||
84 | envP, XMLRPC_TYPE_ERROR(-501), "Value is not a struct. It is type #%d", | |||||
85 | structP->_type); | |||||
86 | retval = -1; | |||||
87 | } else { | |||||
88 | size_t const size = | |||||
89 | XMLRPC_MEMBLOCK_SIZE(_struct_member, &structP->_block)(xmlrpc_mem_block_size(&structP->_block) / sizeof(_struct_member )); | |||||
90 | ||||||
91 | assert((size_t)(int)size == size)(((size_t)(int)size == size) ? (void) (0) : __assert_fail ("(size_t)(int)size == size" , "../../../../libs/xmlrpc-c/src/xmlrpc_struct.c", 91, __PRETTY_FUNCTION__ )); | |||||
92 | /* Because structs are defined to have few enough members */ | |||||
93 | ||||||
94 | retval = (int)size; | |||||
95 | } | |||||
96 | return retval; | |||||
97 | } | |||||
98 | ||||||
99 | ||||||
100 | ||||||
101 | static uint32_t | |||||
102 | hashStructKey(const char * const key, | |||||
103 | size_t const keyLen) { | |||||
104 | ||||||
105 | uint32_t hash; | |||||
106 | size_t i; | |||||
107 | ||||||
108 | XMLRPC_ASSERT(key != NULL)do if (!(key != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 108); while (0); | |||||
109 | ||||||
110 | /* This is the Bernstein hash, optimized for lower case ASCII | |||||
111 | keys. Note that the bytes of such a key differ only in their | |||||
112 | lower 5 bits. | |||||
113 | */ | |||||
114 | for (hash = 0, i = 0; i < keyLen; ++i) | |||||
115 | hash = hash + key[i] + (hash << 5); | |||||
116 | ||||||
117 | return hash; | |||||
118 | } | |||||
119 | ||||||
120 | ||||||
121 | ||||||
122 | /*========================================================================= | |||||
123 | ** find_member | |||||
124 | **========================================================================= | |||||
125 | ** Get the index of the member with the specified key, or -1 if no such | |||||
126 | ** member exists. | |||||
127 | */ | |||||
128 | ||||||
129 | static int | |||||
130 | find_member(xmlrpc_value * const strctP, | |||||
131 | const char * const key, | |||||
132 | size_t const keyLen) { | |||||
133 | ||||||
134 | int retval; | |||||
135 | size_t size, i; | |||||
136 | uint32_t searchHash; | |||||
137 | _struct_member * contents; /* array */ | |||||
138 | bool found; | |||||
139 | size_t foundIndex; /* Meaningful only when 'found' is true */ | |||||
140 | ||||||
141 | XMLRPC_ASSERT_VALUE_OK(strctP)do if (!((strctP) != ((void*)0) && (strctP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 141); while (0); | |||||
142 | XMLRPC_ASSERT(key != NULL)do if (!(key != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 142); while (0); | |||||
143 | foundIndex = 0; /* defeat used-before-set compiler warning */ | |||||
144 | ||||||
145 | /* Look for our key. */ | |||||
146 | searchHash = hashStructKey(key, keyLen); | |||||
147 | size = XMLRPC_MEMBLOCK_SIZE(_struct_member, &strctP->_block)(xmlrpc_mem_block_size(&strctP->_block) / sizeof(_struct_member )); | |||||
148 | contents = XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &strctP->_block)((_struct_member*) xmlrpc_mem_block_contents(&strctP-> _block)); | |||||
149 | for (i = 0, found = false; i < size && !found; ++i) { | |||||
150 | if (contents[i].keyHash == searchHash) { | |||||
151 | xmlrpc_value * const keyvalP = contents[i].key; | |||||
152 | const char * const keystr = | |||||
153 | XMLRPC_MEMBLOCK_CONTENTS(char, &keyvalP->_block)((char*) xmlrpc_mem_block_contents(&keyvalP->_block)); | |||||
154 | size_t const keystrSize = | |||||
155 | XMLRPC_MEMBLOCK_SIZE(char, &keyvalP->_block)(xmlrpc_mem_block_size(&keyvalP->_block) / sizeof(char ))-1; | |||||
156 | if (keystrSize == keyLen && memcmp(key, keystr, keyLen) == 0) { | |||||
157 | found = true; | |||||
158 | foundIndex = i; | |||||
159 | } | |||||
160 | } | |||||
161 | } | |||||
162 | if (found) { | |||||
163 | assert((size_t)(int)foundIndex == foundIndex)(((size_t)(int)foundIndex == foundIndex) ? (void) (0) : __assert_fail ("(size_t)(int)foundIndex == foundIndex", "../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 163, __PRETTY_FUNCTION__)); | |||||
164 | /* Definition of structure says it has few enough members */ | |||||
165 | retval = foundIndex; | |||||
166 | } else | |||||
167 | retval = -1; | |||||
168 | ||||||
169 | return retval; | |||||
170 | } | |||||
171 | ||||||
172 | ||||||
173 | ||||||
174 | /*========================================================================= | |||||
175 | ** xmlrpc_struct_has_key | |||||
176 | **========================================================================= | |||||
177 | */ | |||||
178 | ||||||
179 | int | |||||
180 | xmlrpc_struct_has_key(xmlrpc_env * const envP, | |||||
181 | xmlrpc_value * const strctP, | |||||
182 | const char * const key) { | |||||
183 | ||||||
184 | XMLRPC_ASSERT(key != NULL)do if (!(key != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 184); while (0); | |||||
185 | return xmlrpc_struct_has_key_n(envP, strctP, key, strlen(key)); | |||||
186 | } | |||||
187 | ||||||
188 | ||||||
189 | ||||||
190 | int | |||||
191 | xmlrpc_struct_has_key_n(xmlrpc_env * const envP, | |||||
192 | xmlrpc_value * const strctP, | |||||
193 | const char * const key, | |||||
194 | size_t const key_len) { | |||||
195 | int index; | |||||
196 | ||||||
197 | /* Suppress a compiler warning about uninitialized variables. */ | |||||
198 | index = 0; | |||||
199 | ||||||
200 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c", 200); while (0); | |||||
| ||||||
201 | XMLRPC_ASSERT_VALUE_OK(strctP)do if (!((strctP) != ((void*)0) && (strctP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 201); while (0); | |||||
202 | XMLRPC_ASSERT(key != NULL)do if (!(key != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 202); while (0); | |||||
203 | ||||||
204 | XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT)do if ((strctP)->_type != (XMLRPC_TYPE_STRUCT)) do { xmlrpc_env_set_fault ((envP),((-501)),("Expected " "XMLRPC_TYPE_STRUCT")); goto cleanup ; } while (0); while (0); | |||||
205 | index = find_member(strctP, key, key_len); | |||||
206 | ||||||
207 | cleanup: | |||||
208 | if (envP->fault_occurred) | |||||
| ||||||
209 | return 0; | |||||
210 | return (index >= 0); | |||||
211 | } | |||||
212 | ||||||
213 | ||||||
214 | ||||||
215 | /*========================================================================= | |||||
216 | ** xmlrpc_struct_find_value... | |||||
217 | **========================================================================= | |||||
218 | ** These functions look up a specified key value in a specified struct. | |||||
219 | ** If it exists, they return the value of the struct member. If not, | |||||
220 | ** they return a NULL to indicate such. | |||||
221 | */ | |||||
222 | ||||||
223 | /* It would be a nice extension to be able to look up a key that is | |||||
224 | not a text string. | |||||
225 | */ | |||||
226 | ||||||
227 | void | |||||
228 | xmlrpc_struct_find_value(xmlrpc_env * const envP, | |||||
229 | xmlrpc_value * const structP, | |||||
230 | const char * const key, | |||||
231 | xmlrpc_value ** const valuePP) { | |||||
232 | /*---------------------------------------------------------------------------- | |||||
233 | Given a key, retrieve a value from the struct. If the key is not | |||||
234 | present, return NULL as *valuePP. | |||||
235 | -----------------------------------------------------------------------------*/ | |||||
236 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c", 236); while (0); | |||||
237 | XMLRPC_ASSERT_VALUE_OK(structP)do if (!((structP) != ((void*)0) && (structP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 237); while (0); | |||||
238 | XMLRPC_ASSERT_PTR_OK(key)do if (!((key) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 238); while (0); | |||||
239 | ||||||
240 | if (structP->_type != XMLRPC_TYPE_STRUCT) | |||||
241 | xmlrpc_env_set_fault_formatted( | |||||
242 | envP, XMLRPC_TYPE_ERROR(-501), "Value is not a struct. It is type #%d", | |||||
243 | structP->_type); | |||||
244 | else { | |||||
245 | int index; | |||||
246 | ||||||
247 | /* Get our member index. */ | |||||
248 | index = find_member(structP, key, strlen(key)); | |||||
249 | if (index < 0) | |||||
250 | *valuePP = NULL((void*)0); | |||||
251 | else { | |||||
252 | _struct_member * const members = | |||||
253 | XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block)((_struct_member*) xmlrpc_mem_block_contents(&structP-> _block)); | |||||
254 | *valuePP = members[index].value; | |||||
255 | ||||||
256 | XMLRPC_ASSERT_VALUE_OK(*valuePP)do if (!((*valuePP) != ((void*)0) && (*valuePP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 256); while (0); | |||||
257 | ||||||
258 | xmlrpc_INCREF(*valuePP); | |||||
259 | } | |||||
260 | } | |||||
261 | } | |||||
262 | ||||||
263 | ||||||
264 | ||||||
265 | void | |||||
266 | xmlrpc_struct_find_value_v(xmlrpc_env * const envP, | |||||
267 | xmlrpc_value * const structP, | |||||
268 | xmlrpc_value * const keyP, | |||||
269 | xmlrpc_value ** const valuePP) { | |||||
270 | /*---------------------------------------------------------------------------- | |||||
271 | Given a key, retrieve a value from the struct. If the key is not | |||||
272 | present, return NULL as *valuePP. | |||||
273 | -----------------------------------------------------------------------------*/ | |||||
274 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c", 274); while (0); | |||||
275 | XMLRPC_ASSERT_VALUE_OK(structP)do if (!((structP) != ((void*)0) && (structP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 275); while (0); | |||||
276 | XMLRPC_ASSERT_VALUE_OK(keyP)do if (!((keyP) != ((void*)0) && (keyP)->_type != XMLRPC_TYPE_DEAD )) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 276); while (0); | |||||
277 | ||||||
278 | if (structP->_type != XMLRPC_TYPE_STRUCT) | |||||
279 | xmlrpc_env_set_fault_formatted( | |||||
280 | envP, XMLRPC_TYPE_ERROR(-501), "Value is not a struct. It is type #%d", | |||||
281 | structP->_type); | |||||
282 | else { | |||||
283 | if (keyP->_type != XMLRPC_TYPE_STRING) | |||||
284 | xmlrpc_env_set_fault_formatted( | |||||
285 | envP, XMLRPC_TYPE_ERROR(-501), "Key value is not a string. " | |||||
286 | "It is type #%d", | |||||
287 | keyP->_type); | |||||
288 | else { | |||||
289 | int index; | |||||
290 | ||||||
291 | /* Get our member index. */ | |||||
292 | index = find_member(structP, | |||||
293 | XMLRPC_MEMBLOCK_CONTENTS(char, &keyP->_block)((char*) xmlrpc_mem_block_contents(&keyP->_block)), | |||||
294 | XMLRPC_MEMBLOCK_SIZE(char, &keyP->_block)(xmlrpc_mem_block_size(&keyP->_block) / sizeof(char))-1); | |||||
295 | if (index < 0) | |||||
296 | *valuePP = NULL((void*)0); | |||||
297 | else { | |||||
298 | _struct_member * const members = | |||||
299 | XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block)((_struct_member*) xmlrpc_mem_block_contents(&structP-> _block)); | |||||
300 | *valuePP = members[index].value; | |||||
301 | ||||||
302 | XMLRPC_ASSERT_VALUE_OK(*valuePP)do if (!((*valuePP) != ((void*)0) && (*valuePP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 302); while (0); | |||||
303 | ||||||
304 | xmlrpc_INCREF(*valuePP); | |||||
305 | } | |||||
306 | } | |||||
307 | } | |||||
308 | } | |||||
309 | ||||||
310 | ||||||
311 | ||||||
312 | /*========================================================================= | |||||
313 | ** xmlrpc_struct_read_value... | |||||
314 | **========================================================================= | |||||
315 | ** These fail if no member with the specified key exists. | |||||
316 | ** Otherwise, they are the same as xmlrpc_struct_find_value... | |||||
317 | */ | |||||
318 | ||||||
319 | void | |||||
320 | xmlrpc_struct_read_value_v(xmlrpc_env * const envP, | |||||
321 | xmlrpc_value * const structP, | |||||
322 | xmlrpc_value * const keyP, | |||||
323 | xmlrpc_value ** const valuePP) { | |||||
324 | ||||||
325 | xmlrpc_struct_find_value_v(envP, structP, keyP, valuePP); | |||||
326 | ||||||
327 | if (!envP->fault_occurred) { | |||||
328 | if (*valuePP == NULL((void*)0)) { | |||||
329 | xmlrpc_env_set_fault_formatted( | |||||
330 | envP, XMLRPC_INDEX_ERROR(-502), "No member of struct has key '%.*s'", | |||||
331 | (int)XMLRPC_MEMBLOCK_SIZE(char, &keyP->_block)(xmlrpc_mem_block_size(&keyP->_block) / sizeof(char)), | |||||
332 | XMLRPC_MEMBLOCK_CONTENTS(char, &keyP->_block)((char*) xmlrpc_mem_block_contents(&keyP->_block))); | |||||
333 | } | |||||
334 | } | |||||
335 | } | |||||
336 | ||||||
337 | ||||||
338 | ||||||
339 | void | |||||
340 | xmlrpc_struct_read_value(xmlrpc_env * const envP, | |||||
341 | xmlrpc_value * const structP, | |||||
342 | const char * const key, | |||||
343 | xmlrpc_value ** const valuePP) { | |||||
344 | ||||||
345 | xmlrpc_struct_find_value(envP, structP, key, valuePP); | |||||
346 | ||||||
347 | if (!envP->fault_occurred) { | |||||
348 | if (*valuePP == NULL((void*)0)) { | |||||
349 | xmlrpc_env_set_fault_formatted( | |||||
350 | envP, XMLRPC_INDEX_ERROR(-502), "No member of struct has key '%s'", | |||||
351 | key); | |||||
352 | /* We should fix the error message to format the key for display */ | |||||
353 | } | |||||
354 | } | |||||
355 | } | |||||
356 | ||||||
357 | ||||||
358 | ||||||
359 | /*========================================================================= | |||||
360 | ** xmlrpc_struct_get_value... | |||||
361 | **========================================================================= | |||||
362 | ** These are for backward compatibility. They used to be the only ones. | |||||
363 | ** They're deprecated because they don't acquire a reference to the | |||||
364 | ** value they return. | |||||
365 | */ | |||||
366 | ||||||
367 | xmlrpc_value * | |||||
368 | xmlrpc_struct_get_value_n(xmlrpc_env * const envP, | |||||
369 | xmlrpc_value * const structP, | |||||
370 | const char * const key, | |||||
371 | size_t const keyLen) { | |||||
372 | ||||||
373 | xmlrpc_value * retval; | |||||
374 | xmlrpc_value * keyP; | |||||
375 | ||||||
376 | keyP = xmlrpc_build_value(envP, "s#", key, keyLen); | |||||
377 | if (!envP->fault_occurred) { | |||||
378 | xmlrpc_struct_find_value_v(envP, structP, keyP, &retval); | |||||
379 | ||||||
380 | if (!envP->fault_occurred) { | |||||
381 | if (retval == NULL((void*)0)) { | |||||
382 | xmlrpc_env_set_fault_formatted( | |||||
383 | envP, XMLRPC_INDEX_ERROR(-502), | |||||
384 | "No member of struct has key '%.*s'", | |||||
385 | (int)keyLen, key); | |||||
386 | /* We should fix the error message to format the key | |||||
387 | for display */ | |||||
388 | } else | |||||
389 | /* For backward compatibility. */ | |||||
390 | xmlrpc_DECREF(retval); | |||||
391 | } | |||||
392 | xmlrpc_DECREF(keyP); | |||||
393 | } | |||||
394 | return retval; | |||||
395 | } | |||||
396 | ||||||
397 | ||||||
398 | ||||||
399 | xmlrpc_value * | |||||
400 | xmlrpc_struct_get_value(xmlrpc_env * const envP, | |||||
401 | xmlrpc_value * const strctP, | |||||
402 | const char * const key) { | |||||
403 | ||||||
404 | XMLRPC_ASSERT(key != NULL)do if (!(key != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 404); while (0); | |||||
405 | return xmlrpc_struct_get_value_n(envP, strctP, key, strlen(key)); | |||||
406 | } | |||||
407 | ||||||
408 | ||||||
409 | ||||||
410 | /*========================================================================= | |||||
411 | ** xmlrpc_struct_set_value | |||||
412 | **========================================================================= | |||||
413 | */ | |||||
414 | ||||||
415 | void | |||||
416 | xmlrpc_struct_set_value(xmlrpc_env * const envP, | |||||
417 | xmlrpc_value * const strctP, | |||||
418 | const char * const key, | |||||
419 | xmlrpc_value * const valueP) { | |||||
420 | ||||||
421 | XMLRPC_ASSERT(key != NULL)do if (!(key != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 421); while (0); | |||||
422 | xmlrpc_struct_set_value_n(envP, strctP, key, strlen(key), valueP); | |||||
423 | } | |||||
424 | ||||||
425 | ||||||
426 | ||||||
427 | void | |||||
428 | xmlrpc_struct_set_value_n(xmlrpc_env * const envP, | |||||
429 | xmlrpc_value * const strctP, | |||||
430 | const char * const key, | |||||
431 | size_t const keyLen, | |||||
432 | xmlrpc_value * const valueP) { | |||||
433 | ||||||
434 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c", 434); while (0); | |||||
435 | XMLRPC_ASSERT(key != NULL)do if (!(key != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 435); while (0); | |||||
436 | ||||||
437 | if (xmlrpc_value_type(strctP) != XMLRPC_TYPE_STRUCT) | |||||
438 | xmlrpc_env_set_fault_formatted( | |||||
439 | envP, XMLRPC_TYPE_ERROR(-501), | |||||
440 | "Trying to set value in something not a struct. " | |||||
441 | "Type is %d; struct is %d", | |||||
442 | xmlrpc_value_type(strctP), XMLRPC_TYPE_STRUCT); | |||||
443 | else { | |||||
444 | xmlrpc_value * keyvalP; | |||||
445 | ||||||
446 | /* Get the key as an xmlrpc_value */ | |||||
447 | keyvalP = xmlrpc_build_value(envP, "s#", key, keyLen); | |||||
448 | if (!envP->fault_occurred) | |||||
449 | xmlrpc_struct_set_value_v(envP, strctP, keyvalP, valueP); | |||||
450 | ||||||
451 | xmlrpc_DECREF(keyvalP); | |||||
452 | } | |||||
453 | } | |||||
454 | ||||||
455 | ||||||
456 | ||||||
457 | void | |||||
458 | xmlrpc_struct_set_value_v(xmlrpc_env * const envP, | |||||
459 | xmlrpc_value * const strctP, | |||||
460 | xmlrpc_value * const keyvalP, | |||||
461 | xmlrpc_value * const valueP) { | |||||
462 | ||||||
463 | char *key; | |||||
464 | size_t key_len; | |||||
465 | int index; | |||||
466 | _struct_member *members, *member, new_member; | |||||
467 | xmlrpc_value *old_value; | |||||
468 | ||||||
469 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c", 469); while (0); | |||||
470 | XMLRPC_ASSERT_VALUE_OK(strctP)do if (!((strctP) != ((void*)0) && (strctP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 470); while (0); | |||||
471 | XMLRPC_ASSERT_VALUE_OK(keyvalP)do if (!((keyvalP) != ((void*)0) && (keyvalP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 471); while (0); | |||||
472 | XMLRPC_ASSERT_VALUE_OK(valueP)do if (!((valueP) != ((void*)0) && (valueP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 472); while (0); | |||||
473 | ||||||
474 | XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT)do if ((strctP)->_type != (XMLRPC_TYPE_STRUCT)) do { xmlrpc_env_set_fault ((envP),((-501)),("Expected " "XMLRPC_TYPE_STRUCT")); goto cleanup ; } while (0); while (0); | |||||
475 | XMLRPC_TYPE_CHECK(envP, keyvalP, XMLRPC_TYPE_STRING)do if ((keyvalP)->_type != (XMLRPC_TYPE_STRING)) do { xmlrpc_env_set_fault ((envP),((-501)),("Expected " "XMLRPC_TYPE_STRING")); goto cleanup ; } while (0); while (0); | |||||
476 | ||||||
477 | key = XMLRPC_MEMBLOCK_CONTENTS(char, &keyvalP->_block)((char*) xmlrpc_mem_block_contents(&keyvalP->_block)); | |||||
478 | key_len = XMLRPC_MEMBLOCK_SIZE(char, &keyvalP->_block)(xmlrpc_mem_block_size(&keyvalP->_block) / sizeof(char )) - 1; | |||||
479 | index = find_member(strctP, key, key_len); | |||||
480 | ||||||
481 | if (index >= 0) { | |||||
482 | /* Change the value of an existing member. (But be careful--the | |||||
483 | ** original and new values might be the same object, so watch | |||||
484 | ** the order of INCREF and DECREF calls!) */ | |||||
485 | members = XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &strctP->_block)((_struct_member*) xmlrpc_mem_block_contents(&strctP-> _block)); | |||||
486 | member = &members[index]; | |||||
487 | ||||||
488 | /* Juggle our references. */ | |||||
489 | old_value = member->value; | |||||
490 | member->value = valueP; | |||||
491 | xmlrpc_INCREF(member->value); | |||||
492 | xmlrpc_DECREF(old_value); | |||||
493 | } else { | |||||
494 | /* Add a new member. */ | |||||
495 | new_member.keyHash = hashStructKey(key, key_len); | |||||
496 | new_member.key = keyvalP; | |||||
497 | new_member.value = valueP; | |||||
498 | XMLRPC_MEMBLOCK_APPEND(_struct_member, envP, &strctP->_block,xmlrpc_mem_block_append(envP, &strctP->_block, &new_member , sizeof(_struct_member) * (1)) | |||||
499 | &new_member, 1)xmlrpc_mem_block_append(envP, &strctP->_block, &new_member , sizeof(_struct_member) * (1)); | |||||
500 | XMLRPC_FAIL_IF_FAULT(envP)do { if ((envP)->fault_occurred) goto cleanup; } while (0); | |||||
501 | xmlrpc_INCREF(keyvalP); | |||||
502 | xmlrpc_INCREF(valueP); | |||||
503 | } | |||||
504 | ||||||
505 | cleanup: | |||||
506 | return; | |||||
507 | } | |||||
508 | ||||||
509 | ||||||
510 | ||||||
511 | /* Note that the order of keys and values is undefined, and may change | |||||
512 | when you modify the struct. | |||||
513 | */ | |||||
514 | ||||||
515 | void | |||||
516 | xmlrpc_struct_read_member(xmlrpc_env * const envP, | |||||
517 | xmlrpc_value * const structP, | |||||
518 | unsigned int const index, | |||||
519 | xmlrpc_value ** const keyvalP, | |||||
520 | xmlrpc_value ** const valueP) { | |||||
521 | ||||||
522 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c", 522); while (0); | |||||
523 | XMLRPC_ASSERT_VALUE_OK(structP)do if (!((structP) != ((void*)0) && (structP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 523); while (0); | |||||
524 | XMLRPC_ASSERT_PTR_OK(keyvalP)do if (!((keyvalP) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 524); while (0); | |||||
525 | XMLRPC_ASSERT_PTR_OK(valueP)do if (!((valueP) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 525); while (0); | |||||
526 | ||||||
527 | if (structP->_type != XMLRPC_TYPE_STRUCT) | |||||
528 | xmlrpc_env_set_fault_formatted( | |||||
529 | envP, XMLRPC_TYPE_ERROR(-501), "Attempt to read a struct member " | |||||
530 | "of something that is not a struct"); | |||||
531 | else { | |||||
532 | _struct_member * const members = | |||||
533 | XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block)((_struct_member*) xmlrpc_mem_block_contents(&structP-> _block)); | |||||
534 | size_t const size = | |||||
535 | XMLRPC_MEMBLOCK_SIZE(_struct_member, &structP->_block)(xmlrpc_mem_block_size(&structP->_block) / sizeof(_struct_member )); | |||||
536 | ||||||
537 | if (index >= size) | |||||
538 | xmlrpc_env_set_fault_formatted( | |||||
539 | envP, XMLRPC_INDEX_ERROR(-502), "Index %u is beyond the end of " | |||||
540 | "the %u-member structure", index, (unsigned int)size); | |||||
541 | else { | |||||
542 | _struct_member * const memberP = &members[index]; | |||||
543 | *keyvalP = memberP->key; | |||||
544 | xmlrpc_INCREF(memberP->key); | |||||
545 | *valueP = memberP->value; | |||||
546 | xmlrpc_INCREF(memberP->value); | |||||
547 | } | |||||
548 | } | |||||
549 | } | |||||
550 | ||||||
551 | ||||||
552 | ||||||
553 | void | |||||
554 | xmlrpc_struct_get_key_and_value(xmlrpc_env * const envP, | |||||
555 | xmlrpc_value * const structP, | |||||
556 | int const index, | |||||
557 | xmlrpc_value ** const keyvalP, | |||||
558 | xmlrpc_value ** const valueP) { | |||||
559 | /*---------------------------------------------------------------------------- | |||||
560 | Same as xmlrpc_struct_read_member(), except doesn't take a reference | |||||
561 | to the returned value. | |||||
562 | ||||||
563 | This is obsolete. | |||||
564 | -----------------------------------------------------------------------------*/ | |||||
565 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c", 565); while (0); | |||||
566 | XMLRPC_ASSERT_VALUE_OK(structP)do if (!((structP) != ((void*)0) && (structP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 566); while (0); | |||||
567 | XMLRPC_ASSERT_PTR_OK(keyvalP)do if (!((keyvalP) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 567); while (0); | |||||
568 | XMLRPC_ASSERT_PTR_OK(valueP)do if (!((valueP) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_struct.c" , 568); while (0); | |||||
569 | ||||||
570 | if (index < 0) | |||||
571 | xmlrpc_env_set_fault_formatted( | |||||
572 | envP, XMLRPC_INDEX_ERROR(-502), "Index %d is negative.", index); | |||||
573 | else { | |||||
574 | xmlrpc_struct_read_member(envP, structP, index, keyvalP, valueP); | |||||
575 | if (!envP->fault_occurred) { | |||||
576 | xmlrpc_DECREF(*keyvalP); | |||||
577 | xmlrpc_DECREF(*valueP); | |||||
578 | } | |||||
579 | } | |||||
580 | if (envP->fault_occurred) { | |||||
581 | *keyvalP = NULL((void*)0); | |||||
582 | *valueP = NULL((void*)0); | |||||
583 | } | |||||
584 | } | |||||
585 | ||||||
586 | ||||||
587 | ||||||
588 | /* Copyright (C) 2001 by First Peer, Inc. All rights reserved. | |||||
589 | ** | |||||
590 | ** Redistribution and use in source and binary forms, with or without | |||||
591 | ** modification, are permitted provided that the following conditions | |||||
592 | ** are met: | |||||
593 | ** 1. Redistributions of source code must retain the above copyright | |||||
594 | ** notice, this list of conditions and the following disclaimer. | |||||
595 | ** 2. Redistributions in binary form must reproduce the above copyright | |||||
596 | ** notice, this list of conditions and the following disclaimer in the | |||||
597 | ** documentation and/or other materials provided with the distribution. | |||||
598 | ** 3. The name of the author may not be used to endorse or promote products | |||||
599 | ** derived from this software without specific prior written permission. | |||||
600 | ** | |||||
601 | ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||||
602 | ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
603 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
604 | ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||||
605 | ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||||
606 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||||
607 | ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
608 | ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||||
609 | ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||||
610 | ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
611 | ** SUCH DAMAGE. */ | |||||
612 |