Memory access bug in XMLString2Perl()
Chris Cheung <[email protected]>
| Newsgroups | gmane.text.xml.xerces-p.devel |
|---|---|
| Message-ID | <Pine.LNX.4.44.0312192004210.12995-100000@jupiter.cluster.clc.cuhk.edu.hk> |
Dear all,
I am currently using Xerces-C 2.3.0 and Xerces-Perl 2.3.0-4.
When I use valgrind (a popular memory debugger,
(http://valgrind.kde.org/) to check the following simple program:
------------------------------------------
#!/usr/bin/perl -w
use strict;
use XML::Xerces;
my $xmlString = '<?xml version="1.0"?><A><B>Hello</B></A>';
my $parser = XML::Xerces::XercesDOMParser->new();
$parser->parse(XML::Xerces::MemBufInputSource->new($xmlString));
my $doc = $parser->getDocument();
my $root = $doc->getDocumentElement;
print $root->getAttribute("notExist");
-----------------------------------------
$ valgrind ./parse.pl
valgrind detected invalid memory access like:
==24771== Invalid write of size 1
==24771== at 0x42F06DEA: XMLString2Perl(unsigned short const*)
(Xerces.cpp:1004)
==24771== by 0x4306E53B: _wrap_DOMElement_getAttribute
(Xerces.cpp:59286)
==24771== by 0x402ACCD5: Perl_pp_entersub (in
/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE/libperl.so)
==24771== by 0x402A62E8: Perl_runops_standard (in
/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE/libperl.so)
==24771== Address 0x418CD8FC is 0 bytes after a block of size 0 alloc'd
==24771== at 0x40026268: __builtin_vec_new (in
/usr/lib/valgrind/vgskin_memcheck.so)
==24771== by 0x400262C0: operator new[](unsigned) (in
/usr/lib/valgrind/vgskin_memcheck.so)
==24771== by 0x42F06DAE: XMLString2Perl(unsigned short const*)
(Xerces.cpp:995)
==24771== by 0x4306E53B: _wrap_DOMElement_getAttribute
(Xerces.cpp:59286)
I used -ggdb3 in building Xerces-Perl and hence line number is displayed
in the error message. It seems that
in line 995 of Xerces.cpp:
SV*
XMLString2Perl(const XMLCh* input) {
SV *output;
unsigned int charsEaten = 0;
int length = XMLString::stringLen(input); // string length
XMLByte* res = new XMLByte[length * UTF8_MAXLEN];
// output string
unsigned int total_chars =
UTF8_TRANSCODER->transcodeTo((const XMLCh*) input,
(unsigned int) length,
(XMLByte*) res,
(unsigned int) length*UTF8_MAXLEN,
charsEaten,
XMLTranscoder::UnRep_Throw
);
res[total_chars] = '\0';
The memory to malloc should be (length * UTF8_MAXLEN + 1):
XMLByte* res = new XMLByte[length * UTF8_MAXLEN + 1]; // output
so that the memory for the ending '\0' is not missed.
Thank you for your attention.
--
Best Regards,
Chris Cheung
Center for Large-Scale Computation
Have a nice day!