xmlrpc_support.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
  2. **
  3. ** Redistribution and use in source and binary forms, with or without
  4. ** modification, are permitted provided that the following conditions
  5. ** are met:
  6. ** 1. Redistributions of source code must retain the above copyright
  7. ** notice, this list of conditions and the following disclaimer.
  8. ** 2. Redistributions in binary form must reproduce the above copyright
  9. ** notice, this list of conditions and the following disclaimer in the
  10. ** documentation and/or other materials provided with the distribution.
  11. ** 3. The name of the author may not be used to endorse or promote products
  12. ** derived from this software without specific prior written permission.
  13. **
  14. ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  15. ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  18. ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23. ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24. ** SUCH DAMAGE. */
  25. #include "xmlrpc_config.h"
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30. #ifdef WIN32
  31. # define vsnprintf _vsnprintf
  32. #endif
  33. #include "xmlrpc.h"
  34. #include "xmlrpc_int.h"
  35. #ifdef EFENCE
  36. /* when looking for corruption don't allocate extra slop */
  37. #define BLOCK_ALLOC_MIN (1)
  38. #else
  39. #define BLOCK_ALLOC_MIN (16)
  40. #endif
  41. #define BLOCK_ALLOC_MAX (128 * 1024 * 1024)
  42. #define ERROR_BUFFER_SZ (256)
  43. /*=========================================================================
  44. ** Strings
  45. **=======================================================================*/
  46. void
  47. xmlrpc_strfree(const char * const string) {
  48. free((void*)string);
  49. }
  50. /*=========================================================================
  51. ** Assertions and Error Handling
  52. **=========================================================================
  53. ** Support code for XMLRPC_ASSERT and xmlrpc_env.
  54. */
  55. void xmlrpc_assertion_failed (char* file, int line)
  56. {
  57. fprintf(stderr, "%s:%d: assertion failed\n", file, line);
  58. abort();
  59. }
  60. static char* default_fault_string = "Not enough memory for error message";
  61. void xmlrpc_env_init (xmlrpc_env* env)
  62. {
  63. XMLRPC_ASSERT(env != NULL);
  64. env->fault_occurred = 0;
  65. env->fault_code = 0;
  66. env->fault_string = NULL;
  67. }
  68. void xmlrpc_env_clean (xmlrpc_env* env)
  69. {
  70. XMLRPC_ASSERT(env != NULL);
  71. /* env->fault_string may be one of three things:
  72. ** 1) a NULL pointer
  73. ** 2) a pointer to the default_fault_string
  74. ** 3) a pointer to a malloc'd fault string
  75. ** If we have case (3), we'll need to free it. */
  76. if (env->fault_string && env->fault_string != default_fault_string)
  77. free(env->fault_string);
  78. env->fault_string = XMLRPC_BAD_POINTER;
  79. }
  80. void
  81. xmlrpc_env_set_fault(xmlrpc_env * const env,
  82. int const faultCode,
  83. const char * const faultDescription) {
  84. XMLRPC_ASSERT(env != NULL);
  85. XMLRPC_ASSERT(faultDescription != NULL);
  86. /* Clean up any leftover pointers. */
  87. xmlrpc_env_clean(env);
  88. env->fault_occurred = 1;
  89. env->fault_code = faultCode;
  90. /* Try to copy the fault string. If this fails, use a default. */
  91. env->fault_string = (char*) malloc(strlen(faultDescription) + 1);
  92. if (env->fault_string)
  93. strcpy(env->fault_string, faultDescription);
  94. else
  95. env->fault_string = default_fault_string;
  96. }
  97. void
  98. xmlrpc_env_set_fault_formatted (xmlrpc_env * const envP,
  99. int const code,
  100. const char * const format,
  101. ...) {
  102. va_list args;
  103. char buffer[ERROR_BUFFER_SZ];
  104. XMLRPC_ASSERT(envP != NULL);
  105. XMLRPC_ASSERT(format != NULL);
  106. /* Print our error message to the buffer. */
  107. va_start(args, format);
  108. vsnprintf(buffer, ERROR_BUFFER_SZ, format, args);
  109. va_end(args);
  110. /* vsnprintf is guaranteed to terminate the buffer, but we're paranoid. */
  111. buffer[ERROR_BUFFER_SZ - 1] = '\0';
  112. /* Set the fault. */
  113. xmlrpc_env_set_fault(envP, code, buffer);
  114. }
  115. void xmlrpc_fatal_error (char* file, int line, char* msg)
  116. {
  117. fprintf(stderr, "%s:%d: %s\n", file, line, msg);
  118. exit(1);
  119. }
  120. /*=========================================================================
  121. ** Resource Limits
  122. **=========================================================================
  123. */
  124. static size_t limits[XMLRPC_LAST_LIMIT_ID + 1] = {
  125. XMLRPC_NESTING_LIMIT_DEFAULT,
  126. XMLRPC_XML_SIZE_LIMIT_DEFAULT
  127. };
  128. void xmlrpc_limit_set (int limit_id, size_t value)
  129. {
  130. XMLRPC_ASSERT(0 <= limit_id && limit_id <= XMLRPC_LAST_LIMIT_ID);
  131. limits[limit_id] = value;
  132. }
  133. size_t xmlrpc_limit_get (int limit_id)
  134. {
  135. XMLRPC_ASSERT(0 <= limit_id && limit_id <= XMLRPC_LAST_LIMIT_ID);
  136. return limits[limit_id];
  137. }
  138. /*=========================================================================
  139. ** xmlrpc_mem_block
  140. **=========================================================================
  141. ** We support resizable blocks of memory. We need these just about
  142. ** everywhere.
  143. */
  144. xmlrpc_mem_block *
  145. xmlrpc_mem_block_new(xmlrpc_env * const env,
  146. size_t const size) {
  147. xmlrpc_mem_block* block;
  148. XMLRPC_ASSERT_ENV_OK(env);
  149. block = (xmlrpc_mem_block*) malloc(sizeof(xmlrpc_mem_block));
  150. XMLRPC_FAIL_IF_NULL(block, env, XMLRPC_INTERNAL_ERROR,
  151. "Can't allocate memory block");
  152. xmlrpc_mem_block_init(env, block, size);
  153. XMLRPC_FAIL_IF_FAULT(env);
  154. cleanup:
  155. if (env->fault_occurred) {
  156. if (block)
  157. free(block);
  158. return NULL;
  159. } else {
  160. return block;
  161. }
  162. }
  163. /* Destroy an existing xmlrpc_mem_block, and everything it contains. */
  164. void xmlrpc_mem_block_free (xmlrpc_mem_block* block)
  165. {
  166. XMLRPC_ASSERT(block != NULL);
  167. XMLRPC_ASSERT(block->_block != NULL);
  168. xmlrpc_mem_block_clean(block);
  169. free(block);
  170. }
  171. /* Initialize the contents of the provided xmlrpc_mem_block. */
  172. void xmlrpc_mem_block_init (xmlrpc_env* env,
  173. xmlrpc_mem_block* block,
  174. size_t size)
  175. {
  176. XMLRPC_ASSERT_ENV_OK(env);
  177. XMLRPC_ASSERT(block != NULL);
  178. block->_size = size;
  179. if (size < BLOCK_ALLOC_MIN)
  180. block->_allocated = BLOCK_ALLOC_MIN;
  181. else
  182. block->_allocated = size;
  183. block->_block = (void*) malloc(block->_allocated);
  184. if (!block->_block)
  185. xmlrpc_env_set_fault_formatted(
  186. env, XMLRPC_INTERNAL_ERROR,
  187. "Can't allocate %u-byte memory block",
  188. block->_allocated);
  189. }
  190. /* Deallocate the contents of the provided xmlrpc_mem_block, but not the
  191. ** block itself. */
  192. void xmlrpc_mem_block_clean (xmlrpc_mem_block* block)
  193. {
  194. XMLRPC_ASSERT(block != NULL);
  195. XMLRPC_ASSERT(block->_block != NULL);
  196. free(block->_block);
  197. block->_block = XMLRPC_BAD_POINTER;
  198. }
  199. /* Get the size of the xmlrpc_mem_block. */
  200. size_t
  201. xmlrpc_mem_block_size(const xmlrpc_mem_block * const block) {
  202. XMLRPC_ASSERT(block != NULL);
  203. return block->_size;
  204. }
  205. /* Get the contents of the xmlrpc_mem_block. */
  206. void *
  207. xmlrpc_mem_block_contents(const xmlrpc_mem_block * const block) {
  208. XMLRPC_ASSERT(block != NULL);
  209. return block->_block;
  210. }
  211. /* Resize an xmlrpc_mem_block, preserving as much of the contents as
  212. ** possible. */
  213. void
  214. xmlrpc_mem_block_resize (xmlrpc_env * const env,
  215. xmlrpc_mem_block * const block,
  216. size_t const size) {
  217. size_t proposed_alloc;
  218. void* new_block;
  219. XMLRPC_ASSERT_ENV_OK(env);
  220. XMLRPC_ASSERT(block != NULL);
  221. /* Check to see if we already have enough space. Maybe we'll get lucky. */
  222. if (size <= block->_allocated) {
  223. block->_size = size;
  224. return;
  225. }
  226. /* Calculate a new allocation size. */
  227. #ifdef EFENCE
  228. proposed_alloc = size;
  229. #else
  230. proposed_alloc = block->_allocated;
  231. while (proposed_alloc < size && proposed_alloc <= BLOCK_ALLOC_MAX)
  232. proposed_alloc *= 2;
  233. #endif /* DEBUG_MEM_ERRORS */
  234. if (proposed_alloc > BLOCK_ALLOC_MAX)
  235. XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR, "Memory block too large");
  236. /* Allocate our new memory block. */
  237. new_block = (void*) malloc(proposed_alloc);
  238. XMLRPC_FAIL_IF_NULL(new_block, env, XMLRPC_INTERNAL_ERROR,
  239. "Can't resize memory block");
  240. /* Copy over our data and update the xmlrpc_mem_block struct. */
  241. memcpy(new_block, block->_block, block->_size);
  242. free(block->_block);
  243. block->_block = new_block;
  244. block->_size = size;
  245. block->_allocated = proposed_alloc;
  246. cleanup:
  247. return;
  248. }
  249. /* Append data to an existing xmlrpc_mem_block. */
  250. void
  251. xmlrpc_mem_block_append(xmlrpc_env * const env,
  252. xmlrpc_mem_block * const block,
  253. void * const data,
  254. size_t const len)
  255. {
  256. int size;
  257. XMLRPC_ASSERT_ENV_OK(env);
  258. XMLRPC_ASSERT(block != NULL);
  259. size = block->_size;
  260. xmlrpc_mem_block_resize(env, block, size + len);
  261. XMLRPC_FAIL_IF_FAULT(env);
  262. memcpy(((unsigned char*) block->_block) + size, data, len);
  263. cleanup:
  264. return;
  265. }
  266. void
  267. xmlrpc_traceXml(const char * const label,
  268. const char * const xml,
  269. unsigned int const xmlLength) {
  270. if (getenv("XMLRPC_TRACE_XML")) {
  271. unsigned int nonPrintableCount;
  272. unsigned int i;
  273. nonPrintableCount = 0; /* Initial value */
  274. for (i = 0; i < xmlLength; ++i) {
  275. if (!isprint(xml[i]) && xml[i] != '\n' && xml[i] != '\r')
  276. ++nonPrintableCount;
  277. }
  278. if (nonPrintableCount > 0)
  279. fprintf(stderr, "%s contains %u nonprintable characters.\n",
  280. label, nonPrintableCount);
  281. fprintf(stderr, "%s:\n %.*s\n", label, (int)xmlLength, xml);
  282. }
  283. }