[xslt] CDATA text nodes can cause ctxt->lasttsize to be incorrect, bug?



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

/*
 * 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);
}

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; >

<xsl:output method="text" />

<xsl:template match="/">
  <xsl:text>x</xsl:text>
  <xsl:text>y</xsl:text>
  <xsl:text>Y</xsl:text>
  <xsl:text><![CDATA[z]]></xsl:text>
  <xsl:text>ZZ</xsl:text>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8" ?>
<x/>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]