0

I have a library that contains a default XML file represented as a const char * stored byte by byte.

I want the user to be able to request a handle to this file (as a TiXmlDocument).

Currently, I'm trying to do this by passing this string defaultFile (its defined in its own header file) to TiXmlDocument.Parse(). The Parse() is passing me back a garbage pointer (but not null) which causes a crash on an attempt to call SaveFile().

I'm able to work around this by writing the same defaultFile to a file using:

FILE *file;
file = fopen("temp.prme", "w");
fprintf(file, "%s", defaultParameterFile);
fclose(file);

I create a new TiXmlDocument using the constructor that takes a file path as input. This works, but it's not a real option because I don't want to be saving files to the users machine.

From what I can tell, all the constructor is doing is reading the string from the file, and then sending it straight to the Parse(). I checked the values that were being passed in memory and found very few differences.

When using the constructor method, you must cal LoadFile() afterwards. In LoadFile(), the string being passed to the Parse() was NOT null terminated. Even though defaultFile was. Also, all new lines (which in defaultFile were listed as /r/n, were listed as \n\n.

I tried modifying defaultFile to match what I was seeing from the constructor, and had no luck. Any Suggestions?

For what its worth, defaultFile is laid out roughly like this:

const char defaultFile[] = {
/* 0x00000000 */   0x3C, 0x3F, 0x78, 0x6D,
...
};

It's roughly 9000 lines long, with 16 bytes per line.

Nealon
  • 2,213
  • 6
  • 26
  • 40
  • There have been a few bugs there in the past, but I think they are fixed now. Anyway, you really have to NUL-terminate your string before passing it to `Parse()`. And what is that constructor that loads a file? – rodrigo Apr 08 '14 at 18:27
  • @rodrigo My point is that the constructor isn't doing it, so I don't have control over that, and its working without the null. The documentation for the constructor can be found [here](http://www.grinninglizard.com/tinyxmldocs/classTiXmlDocument.html#e4508b452d0c3061db085f3db27b8396) – Nealon Apr 08 '14 at 18:35
  • In this doc it says that it is the name and filename of the document, not that it loads it. You have to call `LoadFile()`. And that it works without the NULL may be just chance, because it happens to be a NUL byte just after the string, but it _may_ not happen. – rodrigo Apr 08 '14 at 18:53
  • Also note that `TiXmlDocument::LoadFile()` normalizes the end-of-lines so that `Parse()` only sees `\n` and never `\r`. – rodrigo Apr 08 '14 at 18:57
  • @rodrigo you're right, I forgot that I was calling that afterwards. I'll edit to include that. Still, I looked in memory at what the `LoadFile()` was passing to `Parse()` and found that there was no null termination. It was just garbage memory, in this case 0xCD. – Nealon Apr 08 '14 at 18:59
  • In my copy of the source at `TiXmlDocument::LoadFile()`: `assert( q <= (buf+length) ); *q = 0; Parse( buf, 0, encoding );`. See the `0` (`q` points to the middle of `buf`). Then yes, there will be garbage because the buffer has more length than needed, but that will not matter because it will not read past the NUL. – rodrigo Apr 08 '14 at 19:10
  • @rodrigo Thats the point, there is no NUL. – Nealon Apr 08 '14 at 19:12
  • See the `*q = 0;`? There is the NUL byte! Maybe you would prefer to write `\0`, but it is equivalent! – rodrigo Apr 08 '14 at 19:16
  • Ok, that sort of makes sense. Regardless, I tried modifying the string to have a null and not have a null, none of it is working – Nealon Apr 08 '14 at 19:24

1 Answers1

0

When calling into the Parse() directly, I was allocating the TiXmlDocument on the stack. The data was being corrupted by other function calls. I fixed that and everything worked.

Nealon
  • 2,213
  • 6
  • 26
  • 40