CDATA text nodes can cause ctxt->lasttsize to be incorrect, bug?
Noam Postavsky <[email protected]>
| Newsgroups | gmane.comp.gnome.lib.xslt |
|---|---|
| Message-ID | <[email protected]> |
xsltAddTextString (transform.c:708) allocates some extra space to target->content in order to avoid future allocations. If a CDATA node is added after this, the node gets added by xmlAddChild() which will merge the text and realloc() the content which means the extra space is no longer available. The problem is that ctxt->lasttsize still reflects the extra space allocation so a subsequent text node may corrupt memory. I've attached a small program to show the problem. Now this isn't a problem if XML_PARSE_NOCDATA is used because there won't be any CDATA nodes. So is it expected behaviour that libxslt fails when given a stylesheet with CDATA nodes, or is this a bug? thanks, Noam _______________________________________________ xslt mailing list, project page http://xmlsoft.org/XSLT/ [email protected] http://mail.gnome.org/mailman/listinfo/xslt
xslt-crash.c
(application/octet-stream, 2.8 KB)
/*
* adapted from libxslt_tutorial.c:
* http://xmlsoft.org/xslt/tutorial/libxslttutorial.html
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxslt/xslt.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
static const int MAGIC = 0x12345678;
typedef struct {
size_t size;
int magic;
} memheader;
typedef struct {
int magic;
size_t size;
} memfooter;
void* get_mem(memheader *header) {
return ((void*)header) + sizeof(memheader);
}
memheader* get_memheader(void *mem) {
return mem - sizeof(memheader);
}
memfooter* get_memfooter(memheader *header) {
return ((void*) header) + sizeof(memheader) + header->size;
}
void check_head_foot(void *mem) {
memheader *header = get_memheader(mem);
memfooter *footer = get_memfooter(header);
assert(header->magic == MAGIC);
assert(footer->magic == MAGIC);
assert(header->size == footer->size);
}
void checked_free(void *mem) {
if (!mem) return;
check_head_foot(mem);
free(get_memheader(mem));
}
void* checked_malloc(size_t size) {
memfooter *footer;
memheader *header = malloc(size + sizeof(memheader) + sizeof(memfooter));
header->magic = MAGIC;
header->size = size;
footer = get_memfooter(header);
footer->magic = MAGIC;
footer->size = size;
return get_mem(header);
}
void* checked_realloc(void *mem, size_t size) {
memfooter *footer;
memheader *header;
if (mem) check_head_foot(mem);
header = realloc(mem? get_memheader(mem) : NULL, size + sizeof(memheader) + sizeof(memfooter));
header->magic = MAGIC;
header->size = size;
footer = get_memfooter(header);
footer->magic = MAGIC;
footer->size = size;
return get_mem(header);
}
char* checked_strdup(const char *str) {
int len = strlen(str);
char *newstr = checked_malloc(len+1);
memcpy(newstr, str, len);
newstr[len] = '\0';
return newstr;
}
extern int xmlLoadExtDtdDefaultValue;
static void usage(const char *name) {
printf("Usage: %s stylesheet <xsl-file> <xml-file>\n", name);
}
int
main(int argc, char **argv) {
int i = 1;
xsltStylesheetPtr cur;
xmlDocPtr doc, res, style_doc;
if (argc <= 1) {
usage(argv[0]);
return(1);
}
xmlInitMemory();
xmlMemSetup(checked_free, checked_malloc, checked_realloc, checked_strdup);
xmlSubstituteEntitiesDefault(1);
xmlLoadExtDtdDefaultValue = 1;
/* passing XML_PARSE_NOCDATA avoid crash */
style_doc = xmlReadFile(argv[i], NULL, 0);
cur = xsltParseStylesheetDoc(style_doc);
i++;
doc = xmlParseFile(argv[i]);
res = xsltApplyStylesheet(cur, doc, NULL);
xsltSaveResultToFile(stdout, res, cur);
xsltFreeStylesheet(cur);
xmlFreeDoc(res);
xmlFreeDoc(doc);
xsltCleanupGlobals();
xmlCleanupParser();
return(0);
}
crash.xsl
(application/octet-stream, 348 B) - not displayed
crash.xml
(text/pl, 45 B)
<?xml version="1.0" encoding="UTF-8" ?> <x/>