diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 69d93ef0..b150a374 100644 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -347,6 +347,11 @@ const char* StrPair::GetStr() } if ( !entityFound ) { // fixme: treat as error? + // Not a recognized entity: copy the '&' through + // verbatim. The write pointer 'q' can lag behind the + // read pointer 'p' after an earlier entity expansion, + // so '*q' must be assigned or a stale byte is emitted. + *q = *p; ++p; ++q; } diff --git a/xmltest.cpp b/xmltest.cpp index db9df56c..c09ff2ca 100644 --- a/xmltest.cpp +++ b/xmltest.cpp @@ -1203,6 +1203,18 @@ int main( int argc, const char ** argv ) } } + { + // An unrecognized entity following a recognized (expanded) entity must + // not corrupt the '&'. After "&" is collapsed the write pointer lags + // the read pointer, and the following "&bogus;" used to emit a stale + // buffer byte in place of the '&'. See issue #1082. + XMLDocument doc; + doc.Parse( "&&bogus;" ); + XMLTest( "Unrecognized entity after expansion: parse", false, doc.Error() ); + XMLTest( "Unrecognized entity after expansion: text", + "&&bogus;", doc.FirstChildElement( "a" )->GetText() ); + } + { // Suppress entities. const char* passages =