#include <assert.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "expat_config.h"
#include "expat.h"
#include "internal.h"
#include "chardata.h"
#include "minicheck.h"
#include "common.h"
#include "handlers.h"
const char *long_character_data_text
= "<?xml version='1.0' encoding='iso-8859-1'?><s>"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"</s>";
const char *long_cdata_text
= "<s><![CDATA["
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890123456789"
"]]></s>";
const char *get_buffer_test_text
= "<documentwitharidiculouslylongelementnametotease"
"aparticularcorneroftheallocationinXML_GetBuffers"
"othatwecanimprovethecoverageyetagain012345678901"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789abcdef0"
"123456789abcdef0123456789abcdef0123456789>\n<ef0";
XML_Bool g_resumable = XML_FALSE;
XML_Bool g_abortable = XML_FALSE;
int g_chunkSize = 1;
void
tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) {
#ifdef XML_DTD
tcase_add_test(tc, test);
#else
UNUSED_P(tc);
UNUSED_P(test);
#endif
}
void
tcase_add_test__if_xml_ge(TCase *tc, tcase_test_function test) {
#if XML_GE == 1
tcase_add_test(tc, test);
#else
UNUSED_P(tc);
UNUSED_P(test);
#endif
}
void
basic_teardown(void) {
if (g_parser != NULL) {
XML_ParserFree(g_parser);
g_parser = NULL;
}
}
void
_xml_failure(XML_Parser parser, const char *file, int line) {
char buffer[1024];
enum XML_Error err = XML_GetErrorCode(parser);
snprintf(buffer, sizeof(buffer),
" %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD
"u, offset %" XML_FMT_INT_MOD "u)\n reported from %s, line %d\n",
err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser),
XML_GetCurrentColumnNumber(parser), file, line);
_fail(file, line, buffer);
}
enum XML_Status
_XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
int isFinal) {
assert((parser != NULL) && (s != NULL) && (len >= 0));
const int chunksize = g_chunkSize;
if (chunksize > 0) {
for (; len > chunksize; len -= chunksize, s += chunksize) {
enum XML_Status res = XML_Parse(parser, s, chunksize, XML_FALSE);
if (res != XML_STATUS_OK) {
if ((res == XML_STATUS_SUSPENDED) && (len > chunksize)) {
fail("Use of function _XML_Parse_SINGLE_BYTES with a chunk size "
"greater than 0 (from g_chunkSize) does not work well with "
"suspension. Please consider use of plain XML_Parse at this "
"place in your test, instead.");
}
return res;
}
}
}
return XML_Parse(parser, s, len, isFinal);
}
void
_expect_failure(const char *text, enum XML_Error errorCode,
const char *errorMessage, const char *file, int lineno) {
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
== XML_STATUS_OK)
_fail(file, lineno, errorMessage);
if (XML_GetErrorCode(g_parser) != errorCode)
_xml_failure(g_parser, file, lineno);
}
void
_run_character_check(const char *text, const XML_Char *expected,
const char *file, int line) {
CharData storage;
CharData_Init(&storage);
XML_SetUserData(g_parser, &storage);
XML_SetCharacterDataHandler(g_parser, accumulate_characters);
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
== XML_STATUS_ERROR)
_xml_failure(g_parser, file, line);
CharData_CheckXMLChars(&storage, expected);
}
void
_run_attribute_check(const char *text, const XML_Char *expected,
const char *file, int line) {
CharData storage;
CharData_Init(&storage);
XML_SetUserData(g_parser, &storage);
XML_SetStartElementHandler(g_parser, accumulate_attribute);
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
== XML_STATUS_ERROR)
_xml_failure(g_parser, file, line);
CharData_CheckXMLChars(&storage, expected);
}
void
_run_ext_character_check(const char *text, ExtTest *test_data,
const XML_Char *expected, const char *file, int line) {
CharData *const storage = (CharData *)malloc(sizeof(CharData));
CharData_Init(storage);
test_data->storage = storage;
XML_SetUserData(g_parser, test_data);
XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters);
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
== XML_STATUS_ERROR)
_xml_failure(g_parser, file, line);
CharData_CheckXMLChars(storage, expected);
free(storage);
}
#define ALLOC_ALWAYS_SUCCEED (-1)
#define REALLOC_ALWAYS_SUCCEED (-1)
int g_allocation_count = ALLOC_ALWAYS_SUCCEED;
int g_reallocation_count = REALLOC_ALWAYS_SUCCEED;
void *
duff_allocator(size_t size) {
if (g_allocation_count == 0)
return NULL;
if (g_allocation_count != ALLOC_ALWAYS_SUCCEED)
g_allocation_count--;
return malloc(size);
}
void *
duff_reallocator(void *ptr, size_t size) {
if (g_reallocation_count == 0)
return NULL;
if (g_reallocation_count != REALLOC_ALWAYS_SUCCEED)
g_reallocation_count--;
return realloc(ptr, size);
}
static size_t
portable_strnlen(const char *s, size_t maxlen) {
const char *const end = (const char *)memchr(s, '\0', maxlen);
return (end == NULL) ? maxlen : (size_t)(end - s);
}
char *
portable_strndup(const char *s, size_t n) {
if ((s == NULL) || (n == SIZE_MAX)) {
errno = EINVAL;
return NULL;
}
n = portable_strnlen(s, n);
char *const buffer = (char *)malloc(n + 1);
if (buffer == NULL) {
errno = ENOMEM;
return NULL;
}
errno = 0;
memcpy(buffer, s, n);
buffer[n] = '\0';
return buffer;
}