Removed global data buffers to make xml_encode() & co thread-safe, marked some place where the xml encoder truncates data.

This commit is contained in:
Konstantin Olchanski 2018-12-18 10:45:28 -08:00
parent 9c763a0e87
commit 869d98081c

118
mxml.c
View File

@ -114,7 +114,7 @@ static int mxml_suppress_date_flag = 0; /* suppress writing date at the top of f
/* local prototypes */ /* local prototypes */
static PMXML_NODE read_error(PMXML_NODE root, const char *file_name, int line_number, char *error, int error_size, int *error_line, const char *format, ...) MXML_GNUC_PRINTF(7, 8); static PMXML_NODE read_error(PMXML_NODE root, const char *file_name, int line_number, char *error, int error_size, int *error_line, const char *format, ...) MXML_GNUC_PRINTF(7, 8);
static void mxml_encode(char *src, int size, int translate); static void mxml_encode(char* buf, int buf_size, const char *src, int src_len, int translate);
static void mxml_decode(char *str); static void mxml_decode(char *str);
static int mxml_write_subtree(MXML_WRITER *writer, PMXML_NODE tree, int indent); static int mxml_write_subtree(MXML_WRITER *writer, PMXML_NODE tree, int indent);
static int mxml_write_line(MXML_WRITER *writer, const char *line); static int mxml_write_line(MXML_WRITER *writer, const char *line);
@ -124,12 +124,6 @@ static int mxml_find_nodes1(PMXML_NODE tree, const char *xml_path, PMXML_NODE **
static void *mxml_malloc(size_t size); static void *mxml_malloc(size_t size);
static void *mxml_realloc(void *p, size_t size); static void *mxml_realloc(void *p, size_t size);
static void mxml_free(void *p); static void mxml_free(void *p);
static void mxml_deallocate(void);
/*------------------------------------------------------------------*/
static char *_encode_buffer = NULL;
static char *_data_enc = NULL;
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
@ -154,20 +148,6 @@ void mxml_free(void *p)
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
void mxml_deallocate(void)
{
if (_encode_buffer != NULL) {
mxml_free(_encode_buffer);
_encode_buffer = NULL;
}
if (_data_enc != NULL) {
mxml_free(_data_enc);
_data_enc = NULL;
}
}
/*------------------------------------------------------------------*/
int mxml_write_line(MXML_WRITER *writer, const char *line) int mxml_write_line(MXML_WRITER *writer, const char *line)
{ {
unsigned len; unsigned len;
@ -178,7 +158,7 @@ int mxml_write_line(MXML_WRITER *writer, const char *line)
if (writer->buffer_len + len >= writer->buffer_size) { if (writer->buffer_len + len >= writer->buffer_size) {
writer->buffer_size += len + 10000; writer->buffer_size += len + 10000;
writer->buffer = (char *)mxml_realloc(writer->buffer, writer->buffer_size); writer->buffer = (char *)mxml_realloc(writer->buffer, writer->buffer_size);
assert(writer->buffer); assert(writer->buffer);
} }
strcpy(writer->buffer + writer->buffer_len, line); strcpy(writer->buffer + writer->buffer_len, line);
writer->buffer_len += len; writer->buffer_len += len;
@ -283,25 +263,12 @@ MXML_WRITER *mxml_open_file(const char *file_name)
/** /**
* convert '<' '>' '&' '"' ''' into &xx; * convert '<' '>' '&' '"' ''' into &xx;
*/ */
void mxml_encode(char *src, int size, int translate) void mxml_encode(char* buf, int buf_size, const char *src, int src_len, int translate)
{ {
char *ps, *pd; assert(buf_size > 6*src_len); // each input byte is expanded into 6 bytes at most
static int buffer_size = 1000; char *pd = buf;
const char* ps;
assert(size); for (ps = src ; *ps ; ps++) {
if (_encode_buffer == NULL) {
_encode_buffer = (char *) mxml_malloc(buffer_size);
atexit(mxml_deallocate);
}
if (size > buffer_size) {
_encode_buffer = (char *) mxml_realloc(_encode_buffer, size*2);
buffer_size = size;
}
pd = _encode_buffer;
for (ps = src ; *ps && (size_t)pd - (size_t)_encode_buffer < (size_t)(size-10) ; ps++) {
if (translate) { /* tranlate "<", ">", "&", """, "'" */ if (translate) { /* tranlate "<", ">", "&", """, "'" */
switch (*ps) { switch (*ps) {
@ -329,7 +296,7 @@ void mxml_encode(char *src, int size, int translate)
*pd++ = *ps; *pd++ = *ps;
} }
} else { } else {
switch (*ps) { /* translate only illegal XML characters "<" and "&" */ switch (*ps) { /* translate only special XML characters "<" and "&" */
case '<': case '<':
strcpy(pd, "&lt;"); strcpy(pd, "&lt;");
pd += 4; pd += 4;
@ -345,7 +312,7 @@ void mxml_encode(char *src, int size, int translate)
} }
*pd = 0; *pd = 0;
strlcpy(src, _encode_buffer, size); //printf("mxml_encode: size %d, in %d, out %d, [%s] -> [%s]\n", buf_size, src_len, (int)strlen(buf), src, buf);
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
@ -410,7 +377,7 @@ int mxml_set_translate(MXML_WRITER *writer, int flag)
int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent) int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent)
{ {
int i; int i;
char line[1000], name_enc[1000]; char line[1000];
if (writer->element_is_open) { if (writer->element_is_open) {
mxml_write_line(writer, ">\n"); mxml_write_line(writer, ">\n");
@ -420,11 +387,14 @@ int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent)
line[0] = 0; line[0] = 0;
if (indent) if (indent)
for (i=0 ; i<writer->level ; i++) for (i=0 ; i<writer->level ; i++)
strlcat(line, XML_INDENT, sizeof(line)); strlcat(line, XML_INDENT, sizeof(line)); // FIXME: truncated
strlcat(line, "<", sizeof(line)); strlcat(line, "<", sizeof(line));
strlcpy(name_enc, name, sizeof(name_enc));
mxml_encode(name_enc, sizeof(name_enc), writer->translate); unsigned len = strlen(name);
strlcat(line, name_enc, sizeof(line)); unsigned name_enc_size = len*6+10;
char* name_enc = mxml_malloc(name_enc_size);
mxml_encode(name_enc, name_enc_size, name, strlen(name), writer->translate);
strlcat(line, name_enc, sizeof(line)); // FIXME: data will be truncated
/* put element on stack */ /* put element on stack */
if (writer->level == 0) if (writer->level == 0)
@ -432,8 +402,7 @@ int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent)
else else
writer->stack = (char **)mxml_realloc(writer->stack, sizeof(char *)*(writer->level+1)); writer->stack = (char **)mxml_realloc(writer->stack, sizeof(char *)*(writer->level+1));
writer->stack[writer->level] = (char *) mxml_malloc(strlen(name_enc)+1); writer->stack[writer->level] = name_enc;
strcpy(writer->stack[writer->level], name_enc);
writer->level++; writer->level++;
writer->element_is_open = TRUE; writer->element_is_open = TRUE;
writer->data_was_written = FALSE; writer->data_was_written = FALSE;
@ -463,7 +432,6 @@ int mxml_start_element_noindent(MXML_WRITER *writer, const char *name)
int mxml_end_element(MXML_WRITER *writer) int mxml_end_element(MXML_WRITER *writer)
{ {
int i; int i;
char line[1000];
if (writer->level == 0) if (writer->level == 0)
return 0; return 0;
@ -475,18 +443,20 @@ int mxml_end_element(MXML_WRITER *writer)
mxml_free(writer->stack[writer->level]); mxml_free(writer->stack[writer->level]);
if (writer->level == 0) if (writer->level == 0)
mxml_free(writer->stack); mxml_free(writer->stack);
char line[10];
strcpy(line, "/>\n"); strcpy(line, "/>\n");
return mxml_write_line(writer, line) == (int)strlen(line); return mxml_write_line(writer, line) == (int)strlen(line);
} }
char line[1000];
line[0] = 0; line[0] = 0;
if (!writer->data_was_written) { if (!writer->data_was_written) {
for (i=0 ; i<writer->level ; i++) for (i=0 ; i<writer->level ; i++)
strlcat(line, XML_INDENT, sizeof(line)); strlcat(line, XML_INDENT, sizeof(line)); // FIXME: truncated
} }
strlcat(line, "</", sizeof(line)); strlcat(line, "</", sizeof(line));
strlcat(line, writer->stack[writer->level], sizeof(line)); strlcat(line, writer->stack[writer->level], sizeof(line)); // FIXME: truncated
mxml_free(writer->stack[writer->level]); mxml_free(writer->stack[writer->level]);
if (writer->level == 0) if (writer->level == 0)
mxml_free(writer->stack); mxml_free(writer->stack);
@ -503,17 +473,20 @@ int mxml_end_element(MXML_WRITER *writer)
*/ */
int mxml_write_attribute(MXML_WRITER *writer, const char *name, const char *value) int mxml_write_attribute(MXML_WRITER *writer, const char *name, const char *value)
{ {
char name_enc[4096], val_enc[4096], line[8192]; char line[8192];
char buf[6*4096+10];
if (!writer->element_is_open) if (!writer->element_is_open)
return FALSE; return FALSE;
strcpy(name_enc, name); line[0] = 0;
mxml_encode(name_enc, sizeof(name_enc), writer->translate); strlcat(line, " ", sizeof(line));
strcpy(val_enc, value); mxml_encode(buf, sizeof(buf), name, strlen(name), writer->translate);
mxml_encode(val_enc, sizeof(val_enc), writer->translate); strlcat(line, buf, sizeof(line)); // FIXME: truncated
strlcat(line, "=\"", sizeof(line));
sprintf(line, " %s=\"%s\"", name_enc, val_enc); mxml_encode(buf, sizeof(buf), value, strlen(value), writer->translate);
strlcat(line, buf, sizeof(line)); // FIXME: truncated
strlcat(line, "\"", sizeof(line));
return mxml_write_line(writer, line) == (int)strlen(line); return mxml_write_line(writer, line) == (int)strlen(line);
} }
@ -525,8 +498,6 @@ int mxml_write_attribute(MXML_WRITER *writer, const char *name, const char *valu
*/ */
int mxml_write_value(MXML_WRITER *writer, const char *data) int mxml_write_value(MXML_WRITER *writer, const char *data)
{ {
static int data_size = 0;
if (!writer->element_is_open) if (!writer->element_is_open)
return FALSE; return FALSE;
@ -535,17 +506,14 @@ int mxml_write_value(MXML_WRITER *writer, const char *data)
writer->element_is_open = FALSE; writer->element_is_open = FALSE;
writer->data_was_written = TRUE; writer->data_was_written = TRUE;
if (data_size == 0) { unsigned len = strlen(data);
_data_enc = (char *)mxml_malloc(1000); unsigned size = 6*len + 1000;
data_size = 1000; char* buf = mxml_malloc(size);
} else if ((int)strlen(data)*2+1000 > data_size) { strcpy(buf, data);
data_size = 1000+(int)strlen(data)*2; mxml_encode(buf, size, data, len, writer->translate);
_data_enc = (char *)mxml_realloc(_data_enc, data_size); int v = mxml_write_line(writer, buf) == (int)strlen(buf);
} mxml_free(buf);
return v;
strcpy(_data_enc, data);
mxml_encode(_data_enc, data_size, writer->translate);
return mxml_write_line(writer, _data_enc) == (int)strlen(_data_enc);
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
@ -574,19 +542,19 @@ int mxml_write_empty_line(MXML_WRITER *writer)
int mxml_write_comment(MXML_WRITER *writer, const char *string) int mxml_write_comment(MXML_WRITER *writer, const char *string)
{ {
int i; int i;
char line[1000];
if (writer->element_is_open) { if (writer->element_is_open) {
mxml_write_line(writer, ">\n"); mxml_write_line(writer, ">\n");
writer->element_is_open = FALSE; writer->element_is_open = FALSE;
} }
char line[1000];
line[0] = 0; line[0] = 0;
for (i=0 ; i<writer->level ; i++) for (i=0 ; i<writer->level ; i++)
strlcat(line, XML_INDENT, sizeof(line)); strlcat(line, XML_INDENT, sizeof(line)); // FIXME: truncated
strlcat(line, "<!-- ", sizeof(line)); strlcat(line, "<!-- ", sizeof(line));
strlcat(line, string, sizeof(line)); strlcat(line, string, sizeof(line)); // FIXME: truncated
strlcat(line, " -->\n", sizeof(line)); strlcat(line, " -->\n", sizeof(line));
if (mxml_write_line(writer, line) != (int)strlen(line)) if (mxml_write_line(writer, line) != (int)strlen(line))
return FALSE; return FALSE;