From 00ff827f10dcd099459da43dff45f292e0245b68 Mon Sep 17 00:00:00 2001 From: soar0216 Date: Thu, 16 Apr 2026 11:02:52 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E7=B2=BE=E7=AE=80XML=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E4=BF=A1=E6=81=AF=E8=BE=93=E5=87=BA=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构错误信息输出格式,移除冗余信息并优化可读性: - 去掉 Error= 前缀和 ErrorID 字段 - 仅当 lineNum > 0 时显示行号 - 优化上下文信息格式 - 更新测试用例中的硬编码断言 --- .gitignore | 1 + instruction.md | 34 ++++++++++++++++++++++++++++++++++ tinyxml2.cpp | 28 ++++++++++++++++------------ xmltest.cpp | 4 ++-- 4 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 instruction.md diff --git a/.gitignore b/.gitignore index 2c3e2b35..0ab7c86b 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ libtinyxml2.a xmltest vs/debug +.cache/clangd/index diff --git a/instruction.md b/instruction.md new file mode 100644 index 00000000..9bd3e01b --- /dev/null +++ b/instruction.md @@ -0,0 +1,34 @@ +针对xml解释失败时输出格式精简, 新格式规则: +- 去掉 `Error=` 前缀,直接输出枚举名(`ErrorIDToName(error)` 的返回值) +- 去掉 `ErrorID=N (0xN)` 字段(无用内部字段) +- `(line N)` 仅当 `lineNum > 0` 时追加;`lineNum == 0` 时整段省略 +- `` 仅当调用方传入非空 format 时输出,前置 `: ` +格式模板:`[: ][ (line N)]` + +如预期输出对照: +改前: +``` +Error=XML_ERROR_PARSING ErrorID=15 (0xf) Line number=5 +Error=XML_ERROR_MISMATCHED_ELEMENT ErrorID=14 (0xe) Line number=1: XMLElement name=child +Error=XML_ERROR_PARSING_ATTRIBUTE ErrorID=7 (0x7) Line number=7: XMLElement name=item +Error=XML_ERROR_PARSING_DECLARATION ErrorID=2 (0x2) Line number=3: XMLDeclaration value=xml +Error=XML_ERROR_PARSING_ELEMENT ErrorID=1 (0x1) Line number=9: XMLElement name=foo +Error=XML_ERROR_FILE_NOT_FOUND ErrorID=3 (0x3) Line number=0: filename=foo.xml +Error=XML_ERROR_FILE_COULD_NOT_BE_OPENED ErrorID=4 (0x4) Line number=0: filename= +Error=XML_ELEMENT_DEPTH_EXCEEDED ErrorID=18 (0x12) Line number=200: Element nesting is too deep. +``` + +改后: +``` +XML_ERROR_PARSING (line 5) +XML_ERROR_MISMATCHED_ELEMENT: element (line 1) +XML_ERROR_PARSING_ATTRIBUTE: in element (line 7) +XML_ERROR_PARSING_DECLARATION: declaration (line 3) +XML_ERROR_PARSING_ELEMENT: element (line 9) +XML_ERROR_FILE_NOT_FOUND: "foo.xml" +XML_ERROR_FILE_COULD_NOT_BE_OPENED +XML_ELEMENT_DEPTH_EXCEEDED: element nesting is too deep (line 200) +``` +- `xmltest.cpp` 中所有硬编码旧格式字符串的断言须同步更新为新格式,测试需覆盖本次修改内容 + +请帮我完成修改,过程中不用approval diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 56faecbd..06ac7038 100644 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -1164,7 +1164,7 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) } } if ( !wellLocated ) { - _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value()); + _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "declaration <%s>", decl->Value()); _document->DeleteNode( node ); break; } @@ -1199,7 +1199,7 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) } } if ( mismatch ) { - _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name()); + _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "element <%s>", ele->Name()); _document->DeleteNode( node ); break; } @@ -1988,7 +1988,7 @@ char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr ) while( p ) { p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); if ( !(*p) ) { - _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "XMLElement name=%s", Name() ); + _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "element <%s>", Name() ); return 0; } @@ -2003,7 +2003,7 @@ char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr ) p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr ); if ( !p || Attribute( attrib->Name() ) ) { DeleteAttribute( attrib ); - _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "XMLElement name=%s", Name() ); + _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "in element <%s>", Name() ); return 0; } // There is a minor bug here: if the attribute in the source xml @@ -2371,14 +2371,14 @@ XMLError XMLDocument::LoadFile( const char* filename ) { if ( !filename ) { TIXMLASSERT( false ); - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=" ); + SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, 0 ); return _errorID; } Clear(); FILE* fp = callfopen( filename, "rb" ); if ( !fp ) { - SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename ); + SetError( XML_ERROR_FILE_NOT_FOUND, 0, "\"%s\"", filename ); return _errorID; } LoadFile( fp ); @@ -2444,13 +2444,13 @@ XMLError XMLDocument::SaveFile( const char* filename, bool compact ) { if ( !filename ) { TIXMLASSERT( false ); - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=" ); + SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, 0 ); return _errorID; } FILE* fp = callfopen( filename, "w" ); if ( !fp ) { - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename ); + SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "\"%s\"", filename ); return _errorID; } SaveFile(fp, compact); @@ -2530,9 +2530,7 @@ void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... const size_t BUFFER_SIZE = 1000; char* buffer = new char[BUFFER_SIZE]; - TIXMLASSERT(sizeof(error) <= sizeof(int)); - TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d", - ErrorIDToName(error), static_cast(error), static_cast(error), lineNum); + TIXML_SNPRINTF(buffer, BUFFER_SIZE, "%s", ErrorIDToName(error)); if (format) { size_t len = strlen(buffer); @@ -2544,6 +2542,12 @@ void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... TIXML_VSNPRINTF(buffer + len, BUFFER_SIZE - len, format, va); va_end(va); } + + if (lineNum > 0) { + size_t len = strlen(buffer); + TIXML_SNPRINTF(buffer + len, BUFFER_SIZE - len, " (line %d)", lineNum); + } + _errorStr.SetStr(buffer); delete[] buffer; } @@ -2593,7 +2597,7 @@ void XMLDocument::PushDepth() { _parsingDepth++; if (_parsingDepth == TINYXML2_MAX_ELEMENT_DEPTH) { - SetError(XML_ELEMENT_DEPTH_EXCEEDED, _parseCurLineNum, "Element nesting is too deep." ); + SetError(XML_ELEMENT_DEPTH_EXCEEDED, _parseCurLineNum, "element nesting is too deep" ); } } diff --git a/xmltest.cpp b/xmltest.cpp index d058707b..818bdc99 100644 --- a/xmltest.cpp +++ b/xmltest.cpp @@ -576,7 +576,7 @@ int main( int argc, const char ** argv ) XMLTest( "Bad XML", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() ); const char* errorStr = doc.ErrorStr(); XMLTest("Formatted error string", - "Error=XML_ERROR_PARSING_ATTRIBUTE ErrorID=7 (0x7) Line number=3: XMLElement name=wrong", + "XML_ERROR_PARSING_ATTRIBUTE: in element (line 3)", errorStr); } @@ -1311,7 +1311,7 @@ int main( int argc, const char ** argv ) // But be sure there is an error string! const char* errorStr = doc.ErrorStr(); XMLTest("Error string should be set", - "Error=XML_ERROR_EMPTY_DOCUMENT ErrorID=13 (0xd) Line number=0", + "XML_ERROR_EMPTY_DOCUMENT", errorStr); } From 84321dd80c92af0ff96389d5c049de2dc0bfa5d1 Mon Sep 17 00:00:00 2001 From: soar0216 Date: Thu, 16 Apr 2026 12:19:41 +0800 Subject: [PATCH 2/2] =?UTF-8?q?test(xmltest):=20=E6=B7=BB=E5=8A=A0XML?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E5=AD=97=E7=AC=A6=E4=B8=B2=E7=9A=84=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加多个测试用例来验证不同XML解析错误场景下的错误字符串输出,包括文件打开失败、文件未找到、声明解析错误、元素解析错误等场景。确保错误信息格式正确且包含相关上下文信息。 --- xmltest.cpp | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/xmltest.cpp b/xmltest.cpp index 818bdc99..6fd89574 100644 --- a/xmltest.cpp +++ b/xmltest.cpp @@ -2316,6 +2316,7 @@ int main( int argc, const char ** argv ) XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() ); doc.SaveFile( "./no/such/path/pretty.xml" ); XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() ); + XMLTest( "File could not be opened error string", "XML_ERROR_FILE_COULD_NOT_BE_OPENED: \"./no/such/path/pretty.xml\"", doc.ErrorStr() ); doc.SaveFile( "./resources/out/compact.xml", true ); XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() ); } @@ -2327,7 +2328,8 @@ int main( int argc, const char ** argv ) XMLTest( "Should be no error initially", false, doc.Error() ); doc.LoadFile( "resources/no-such-file.xml" ); XMLTest( "No such file - should fail", true, doc.Error() ); - + XMLTest( "File not found error string", "XML_ERROR_FILE_NOT_FOUND: \"resources/no-such-file.xml\"", doc.ErrorStr() ); + doc.LoadFile("resources/dream.xml"); XMLTest("Error should be cleared", false, doc.Error()); @@ -2366,6 +2368,14 @@ int main( int argc, const char ** argv ) XMLTest("Test that declaration inside a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() ); } + { + XMLDocument doc; + const char* xml = ""; + doc.Parse(xml); + XMLTest("Parsing declaration error with context", XML_ERROR_PARSING_DECLARATION, doc.ErrorID()); + XMLTest("Parsing declaration error string", "XML_ERROR_PARSING_DECLARATION: declaration (line 1)", doc.ErrorStr()); + } + { // No matter - before or after successfully parsing a text - // calling XMLDocument::Value() used to cause an assert in debug. @@ -2381,6 +2391,22 @@ int main( int argc, const char ** argv ) delete doc; } + { + XMLDocument doc; + const char* xml = "\n (line 2)", doc.ErrorStr()); + } + + { + XMLDocument doc; + const char* xml = "\n foo \n"; + doc.Parse(xml); + XMLTest("Parsing error", XML_ERROR_PARSING, doc.ErrorID()); + XMLTest("Parsing error string", "XML_ERROR_PARSING (line 1)", doc.ErrorStr()); + } + { XMLDocument doc; for( int i = 0; i < XML_ERROR_COUNT; i++ ) { @@ -2452,6 +2478,13 @@ int main( int argc, const char ** argv ) XMLTest("Stack overflow prevented.", XML_ELEMENT_DEPTH_EXCEEDED, doc.ErrorID()); } } + + { + XMLDocument doc; + doc.LoadFile("./resources/xmltest-5330.xml"); + XMLTest("Element depth exceeded error", XML_ELEMENT_DEPTH_EXCEEDED, doc.ErrorID()); + XMLTest("Element depth exceeded error string", "XML_ELEMENT_DEPTH_EXCEEDED: element nesting is too deep (line 1)", doc.ErrorStr()); + } { const char* TESTS[] = { "./resources/xmltest-5662204197076992.xml", // Security-level performance issue. @@ -2666,10 +2699,7 @@ int main( int argc, const char ** argv ) doc.Parse(xml); XMLTest("Test mismatched elements.", true, doc.Error()); XMLTest("Test mismatched elements.", XML_ERROR_MISMATCHED_ELEMENT, doc.ErrorID()); - // For now just make sure calls work & doesn't crash. - // May solidify the error output in the future. - printf("%s\n", doc.ErrorStr()); - doc.PrintError(); + XMLTest("Mismatched element error string", "XML_ERROR_MISMATCHED_ELEMENT: element (line 1)", doc.ErrorStr()); } // ---------- CVE-2024-50615 -----------