File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/xmlrpc_struct.c |
Location: | line 115, column 23 |
Description: | Array access (from variable 'key') results in a null pointer dereference |
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 |