First of all, thank you for the clue stick re -1
for the size, I totally misinterpreted the description of the change…
As for providing a test for the free() issue, of course I can’t… The oldest version I could find atm was 2.12.10 and naturally xmlFreeParserInputBuffer()
segfaulted there too with an invalid pointer / double free after using xmlIOParseDTD()
.
It was this silly snippet, btw:
#define KC_DTD "\
<!ELEMENT kc (keychain)*> \
\
<!ELEMENT keychain (key)*> \
<!ATTLIST keychain \
nme CDATA #REQUIRED \
dscription CDATA #REQUIRED \
ceated CDATA #REQUIRED \
mdified CDATA #REQUIRED> \
\
<!ELEMENT key EMPTY> \
<!ATTLIST key \
name CDATA #REQUIRED \
value CDATA #REQUIRED \
created CDATA #REQUIRED \
modified CDATA #REQUIRED> \
"
#include <stdio.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/xmlversion.h>
int main(int argc, char *argv[]) {
xmlParserInputBufferPtr buf = NULL;
xmlDtdPtr dtd = NULL;
buf = xmlParserInputBufferCreateMem(KC_DTD,
sizeof(KC_DTD) - (LIBXML_VERSION < 21401 ? 0 : 1),
XML_CHAR_ENCODING_NONE);
if (!buf) {
xmlGenericError(xmlGenericErrorContext, "ERROR: Could not allocate buffer for DTD.\n");
exit(1);
}
dtd = xmlIOParseDTD(NULL, buf, XML_CHAR_ENCODING_NONE);
if (!dtd) {
xmlGenericError(xmlGenericErrorContext, "ERROR: Could not parse DTD.\n");
exit(1);
}
xmlFreeParserInputBuffer(buf);
/*
xmlFreeParserInputBuffer(buf);
*/
}
So either I tested this veery long ago (the commit for the comment in my code dates back to 2013, I’m not even sure which version I was using back then), or it was never actually an issue; it might’ve been that it was on a code path that was already exiting (thus the cleaning up) because of the validation issue, and I actually missed the memory corruption late in the game.
I wouldn’t be surprised if the code for xmlIOParseDTD()
in libxml or at least the part that does its clean-up would not have been touched for at least as long a time, too, and it was simply PEBKAC on my end.
Anyway, thanks again for the quick pointer!
Daniel