1 /* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
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.
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
26 #include "xmlrpc_config.h"
34 # define vsnprintf _vsnprintf
38 #include "xmlrpc_int.h"
41 /* when looking for corruption don't allocate extra slop */
42 #define BLOCK_ALLOC_MIN (1)
44 #define BLOCK_ALLOC_MIN (16)
46 #define BLOCK_ALLOC_MAX (128 * 1024 * 1024)
48 #define ERROR_BUFFER_SZ (256)
51 /*=========================================================================
53 **=======================================================================*/
56 xmlrpc_strfree(const char * const string
) {
61 /*=========================================================================
62 ** Assertions and Error Handling
63 **=========================================================================
64 ** Support code for XMLRPC_ASSERT and xmlrpc_env.
67 void xmlrpc_assertion_failed (char* file
, int line
)
69 fprintf(stderr
, "%s:%d: assertion failed\n", file
, line
);
73 static char* default_fault_string
= "Not enough memory for error message";
75 void xmlrpc_env_init (xmlrpc_env
* env
)
77 XMLRPC_ASSERT(env
!= NULL
);
79 env
->fault_occurred
= 0;
81 env
->fault_string
= NULL
;
84 void xmlrpc_env_clean (xmlrpc_env
* env
)
86 XMLRPC_ASSERT(env
!= NULL
);
88 /* env->fault_string may be one of three things:
90 ** 2) a pointer to the default_fault_string
91 ** 3) a pointer to a malloc'd fault string
92 ** If we have case (3), we'll need to free it. */
93 if (env
->fault_string
&& env
->fault_string
!= default_fault_string
)
94 free(env
->fault_string
);
95 env
->fault_string
= XMLRPC_BAD_POINTER
;
101 xmlrpc_env_set_fault(xmlrpc_env
* const env
,
103 const char * const faultDescription
) {
105 XMLRPC_ASSERT(env
!= NULL
);
106 XMLRPC_ASSERT(faultDescription
!= NULL
);
108 /* Clean up any leftover pointers. */
109 xmlrpc_env_clean(env
);
111 env
->fault_occurred
= 1;
112 env
->fault_code
= faultCode
;
114 /* Try to copy the fault string. If this fails, use a default. */
115 env
->fault_string
= (char*) malloc(strlen(faultDescription
) + 1);
116 if (env
->fault_string
)
117 strcpy(env
->fault_string
, faultDescription
);
119 env
->fault_string
= default_fault_string
;
125 xmlrpc_env_set_fault_formatted (xmlrpc_env
* const envP
,
127 const char * const format
,
130 char buffer
[ERROR_BUFFER_SZ
];
132 XMLRPC_ASSERT(envP
!= NULL
);
133 XMLRPC_ASSERT(format
!= NULL
);
135 /* Print our error message to the buffer. */
136 va_start(args
, format
);
137 vsnprintf(buffer
, ERROR_BUFFER_SZ
, format
, args
);
140 /* vsnprintf is guaranteed to terminate the buffer, but we're paranoid. */
141 buffer
[ERROR_BUFFER_SZ
- 1] = '\0';
144 xmlrpc_env_set_fault(envP
, code
, buffer
);
149 void xmlrpc_fatal_error (char* file
, int line
, char* msg
)
151 fprintf(stderr
, "%s:%d: %s\n", file
, line
, msg
);
156 /*=========================================================================
158 **=========================================================================
161 static size_t limits
[XMLRPC_LAST_LIMIT_ID
+ 1] = {
162 XMLRPC_NESTING_LIMIT_DEFAULT
,
163 XMLRPC_XML_SIZE_LIMIT_DEFAULT
166 void xmlrpc_limit_set (int limit_id
, size_t value
)
168 XMLRPC_ASSERT(0 <= limit_id
&& limit_id
<= XMLRPC_LAST_LIMIT_ID
);
169 limits
[limit_id
] = value
;
172 size_t xmlrpc_limit_get (int limit_id
)
174 XMLRPC_ASSERT(0 <= limit_id
&& limit_id
<= XMLRPC_LAST_LIMIT_ID
);
175 return limits
[limit_id
];
179 /*=========================================================================
181 **=========================================================================
182 ** We support resizable blocks of memory. We need these just about
187 xmlrpc_mem_block_new(xmlrpc_env
* const env
,
189 xmlrpc_mem_block
* block
;
191 XMLRPC_ASSERT_ENV_OK(env
);
193 block
= (xmlrpc_mem_block
*) malloc(sizeof(xmlrpc_mem_block
));
194 XMLRPC_FAIL_IF_NULL(block
, env
, XMLRPC_INTERNAL_ERROR
,
195 "Can't allocate memory block");
197 xmlrpc_mem_block_init(env
, block
, size
);
198 XMLRPC_FAIL_IF_FAULT(env
);
201 if (env
->fault_occurred
) {
210 /* Destroy an existing xmlrpc_mem_block, and everything it contains. */
211 void xmlrpc_mem_block_free (xmlrpc_mem_block
* block
)
213 XMLRPC_ASSERT(block
!= NULL
);
214 XMLRPC_ASSERT(block
->_block
!= NULL
);
216 xmlrpc_mem_block_clean(block
);
220 /* Initialize the contents of the provided xmlrpc_mem_block. */
221 void xmlrpc_mem_block_init (xmlrpc_env
* env
,
222 xmlrpc_mem_block
* block
,
225 XMLRPC_ASSERT_ENV_OK(env
);
226 XMLRPC_ASSERT(block
!= NULL
);
229 if (size
< BLOCK_ALLOC_MIN
)
230 block
->_allocated
= BLOCK_ALLOC_MIN
;
232 block
->_allocated
= size
;
234 block
->_block
= (void*) malloc(block
->_allocated
);
236 xmlrpc_env_set_fault_formatted(
237 env
, XMLRPC_INTERNAL_ERROR
,
238 "Can't allocate %u-byte memory block",
242 /* Deallocate the contents of the provided xmlrpc_mem_block, but not the
244 void xmlrpc_mem_block_clean (xmlrpc_mem_block
* block
)
246 XMLRPC_ASSERT(block
!= NULL
);
247 XMLRPC_ASSERT(block
->_block
!= NULL
);
250 block
->_block
= XMLRPC_BAD_POINTER
;
255 /* Get the size of the xmlrpc_mem_block. */
257 xmlrpc_mem_block_size(const xmlrpc_mem_block
* const block
) {
259 XMLRPC_ASSERT(block
!= NULL
);
265 /* Get the contents of the xmlrpc_mem_block. */
267 xmlrpc_mem_block_contents(const xmlrpc_mem_block
* const block
) {
269 XMLRPC_ASSERT(block
!= NULL
);
270 return block
->_block
;
275 /* Resize an xmlrpc_mem_block, preserving as much of the contents as
278 xmlrpc_mem_block_resize (xmlrpc_env
* const env
,
279 xmlrpc_mem_block
* const block
,
282 size_t proposed_alloc
;
285 XMLRPC_ASSERT_ENV_OK(env
);
286 XMLRPC_ASSERT(block
!= NULL
);
288 /* Check to see if we already have enough space. Maybe we'll get lucky. */
289 if (size
<= block
->_allocated
) {
294 /* Calculate a new allocation size. */
296 proposed_alloc
= size
;
298 proposed_alloc
= block
->_allocated
;
299 while (proposed_alloc
< size
&& proposed_alloc
<= BLOCK_ALLOC_MAX
)
301 #endif /* DEBUG_MEM_ERRORS */
303 if (proposed_alloc
> BLOCK_ALLOC_MAX
)
304 XMLRPC_FAIL(env
, XMLRPC_INTERNAL_ERROR
, "Memory block too large");
306 /* Allocate our new memory block. */
307 new_block
= (void*) malloc(proposed_alloc
);
308 XMLRPC_FAIL_IF_NULL(new_block
, env
, XMLRPC_INTERNAL_ERROR
,
309 "Can't resize memory block");
311 /* Copy over our data and update the xmlrpc_mem_block struct. */
312 memcpy(new_block
, block
->_block
, block
->_size
);
314 block
->_block
= new_block
;
316 block
->_allocated
= proposed_alloc
;
322 /* Append data to an existing xmlrpc_mem_block. */
324 xmlrpc_mem_block_append(xmlrpc_env
* const env
,
325 xmlrpc_mem_block
* const block
,
331 XMLRPC_ASSERT_ENV_OK(env
);
332 XMLRPC_ASSERT(block
!= NULL
);
335 xmlrpc_mem_block_resize(env
, block
, size
+ len
);
336 XMLRPC_FAIL_IF_FAULT(env
);
338 memcpy(((unsigned char*) block
->_block
) + size
, data
, len
);
347 xmlrpc_traceXml(const char * const label
,
348 const char * const xml
,
349 unsigned int const xmlLength
) {
351 if (getenv("XMLRPC_TRACE_XML")) {
352 unsigned int nonPrintableCount
;
355 nonPrintableCount
= 0; /* Initial value */
357 for (i
= 0; i
< xmlLength
; ++i
) {
358 if (!isprint((int)(xml
[i
])) && xml
[i
] != '\n' && xml
[i
] != '\r')
361 if (nonPrintableCount
> 0)
362 fprintf(stderr
, "%s contains %u nonprintable characters.\n",
363 label
, nonPrintableCount
);
365 fprintf(stderr
, "%s:\n %.*s\n", label
, (int)xmlLength
, xml
);