Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve robustness of XmlTreeLib #458

Open
wants to merge 2 commits into
base: release/202311
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 31 additions & 3 deletions XmlSupportPkg/Library/XmlTreeLib/XmlTreeLib.c
Expand Up @@ -877,14 +877,15 @@ BuildNodeList (
//
Status = RtlXmlNextToken (&State, &Next, FALSE);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Failed to get the next token, Status = 0x%x\n", Status));
DEBUG ((EFI_D_ERROR, "Failed to get the next token, Status = %r\n", Status)); // MS_CHANGE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MS_CHANGE tags aren't needed for the mu_plus repo (since this entire repo represents mu value adds). For future reference, MU_CHANGE is preferred for repos that do have upstream components that we track changes against.

goto Exit;
} else if (Next.fError) {
//
// Errors in parse, such as bad characters, come out here in the
// fError member
//
DEBUG ((EFI_D_ERROR, "Error during tokenization, Status = 0x%x\n", Next.fError));
DEBUG ((EFI_D_ERROR, "Error during tokenization, Next.fError = %d\n", Next.fError)); // MS_CHANGE
Status = EFI_ABORTED; // MS_CHANGE
goto Exit;
}

Expand Down Expand Up @@ -1071,7 +1072,7 @@ BuildNodeList (
//
Status = AddAttributeToNode (CurrentNode, AttributeName, AttributeValue);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "ERROR: AddAttributeToNode() failed, Status = 0x%x\n", Status));
DEBUG ((EFI_D_ERROR, "ERROR: AddAttributeToNode() failed, Status = %r\n", Status)); // MS_CHANGE
goto Exit;
}
} else if (Next.State == XTSS_ENDELEMENT_NAME) {
Expand Down Expand Up @@ -1105,6 +1106,20 @@ BuildNodeList (
//
if (CurrentNode) {
CurrentNode = CurrentNode->ParentNode;
// MS_CHANGE [begin]
//
// Topmost node, ignore tailing characters
//
// DONE-CCC:
// See also, TODO-AAA and TODO-BBB in `xml_fasterxml.c`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave full comments, please don't use annotations like DONE-CCC or TODO-AAA.

//
DEBUG ((DEBUG_VERBOSE, "New CurrentNode, %p\n", CurrentNode));
if (CurrentNode == NULL) {
DEBUG ((DEBUG_VERBOSE, "At the end of the Root node\n"));
break;
}

// MS_CHANGE [end]
}
} else if (Next.State == XTSS_ELEMENT_CLOSE_EMPTY) {
DEBUG ((DEBUG_VERBOSE, "XTSS_ELEMENT_CLOSE_EMPTY, empty close\n"));
Expand All @@ -1115,6 +1130,19 @@ BuildNodeList (
//
if (CurrentNode) {
CurrentNode = CurrentNode->ParentNode;
DEBUG ((DEBUG_VERBOSE, "New CurrentNode, %p\n", CurrentNode));

// MS_CHANGE [begin]
//
// DONE-CCC-2:
//
DEBUG ((DEBUG_VERBOSE, "New CurrentNode, %p\n", CurrentNode));
if (CurrentNode == NULL) {
DEBUG ((DEBUG_VERBOSE, "At the end of the Root node\n"));
break;
}

// MS_CHANGE [end]
}
}

Expand Down
24 changes: 24 additions & 0 deletions XmlSupportPkg/Library/XmlTreeLib/fasterxml/xml_fasterxml.c
Expand Up @@ -2700,6 +2700,22 @@ RtlXmlNextToken (
pToken->fError = TRUE;
return success;
}
// MS_CHANGE
//
// TODO-BBB: See TODO-AAA
//
// if (pRawToken->TokenName == NTXML_RAWTOKEN_ERROR) {
// pToken->fError = TRUE;
// success = EFI_ABORTED;
// return success;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of commenting out the code, we can remove it. If it is helpful, do leave a full comment explaining why we don't check if the TokenName == NTXML_RAWTOKEN_ERROR.

// }
//
// Why TODO?
// If we turn on this, we will be endless on other place..
//
// Work around?
// See DONE-CCC in `XmlTreeLib.c`
//

cbTotalTokenLength = pRawToken->Run.cbData;

Expand Down Expand Up @@ -2946,6 +2962,14 @@ RtlXmlNextToken (

cbTotalTokenLength = pRawToken->Run.cbData;

// MS_CHANGE
//
// TODO-AAA:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this TODO fixable now?

// if we encounter a NTXML_RAWTOKEN_ERROR,
// we will run into endless XTSS_STREAM_HYPERSPACE
//
// DEBUG ((DEBUG_VERBOSE, "pRawToken->TokenName = %d\n", pRawToken->TokenName));

NextState = XTSS_STREAM_HYPERSPACE;
}

Expand Down
41 changes: 41 additions & 0 deletions XmlSupportPkg/Test/UnitTest/XmlTreeLib/TestData.h
Expand Up @@ -42,6 +42,47 @@ typedef struct {
XmlNode *Node;
} XmlTestContext;

CONST CHAR8 VerySimpleElementsOnly1[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<RootNode>"
"abcd-1"
"</RootNode>";

CONST CHAR8 VerySimpleElementsOnly2[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<RootNode/>";

CONST CHAR8 VerySimpleElementsOnly3[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<RootNode>"
"abcd-3"
"</RootNode>\r\n\xcd\xcd";

CONST CHAR8 VerySimpleElementsOnly4[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<RootNode/>\r\n\xcd\xcd";

CONST CHAR8 VerySimpleElementsOnly5[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<RootNode>"
"abcd-5"
"</RootNode>"
"<RootNode2>"
"xyz-5"
"</RootNode2>";

CONST CHAR8 VerySimpleElementsOnly6[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<RootNode/>"
"<RootNode2/>";

XmlTestContext VerySimpleElementsOnly1Context = { 1, 0, 1, 0, VerySimpleElementsOnly1, NULL, NULL };
XmlTestContext VerySimpleElementsOnly2Context = { 1, 0, 1, 0, VerySimpleElementsOnly2, NULL, NULL };
XmlTestContext VerySimpleElementsOnly3Context = { 1, 0, 1, 0, VerySimpleElementsOnly3, NULL, NULL };
XmlTestContext VerySimpleElementsOnly4Context = { 1, 0, 1, 0, VerySimpleElementsOnly4, NULL, NULL };
XmlTestContext VerySimpleElementsOnly5Context = { 1, 0, 1, 0, VerySimpleElementsOnly5, NULL, NULL };
XmlTestContext VerySimpleElementsOnly6Context = { 1, 0, 1, 0, VerySimpleElementsOnly6, NULL, NULL };

CONST CHAR8 SimpleElementsOnly[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<RootNode>"
Expand Down
7 changes: 7 additions & 0 deletions XmlSupportPkg/Test/UnitTest/XmlTreeLib/XmlTreeLibUnitTests.c
Expand Up @@ -521,6 +521,13 @@ UnitTestingEntry (
goto EXIT;
}

AddTestCase (InputTestSuite, "Parse Valid XML with a very simple root", "ValidElements", ParseValidXml, NULL, CleanUpXmlTestContext, &VerySimpleElementsOnly1Context);
AddTestCase (InputTestSuite, "Parse Valid XML with a very simple empty tag root", "ValidElements", ParseValidXml, NULL, CleanUpXmlTestContext, &VerySimpleElementsOnly2Context);
AddTestCase (InputTestSuite, "Parse Valid XML with a very simple root, tailing with uninitialized memory", "ValidElements", ParseValidXml, NULL, CleanUpXmlTestContext, &VerySimpleElementsOnly3Context);
AddTestCase (InputTestSuite, "Parse Valid XML with a very simple empty tag root, tailing with uninitialized memory", "ValidElements", ParseValidXml, NULL, CleanUpXmlTestContext, &VerySimpleElementsOnly4Context);
AddTestCase (InputTestSuite, "Parse Valid XML with two very simple roots, report only first root", "ValidElements", ParseValidXml, NULL, CleanUpXmlTestContext, &VerySimpleElementsOnly5Context);
AddTestCase (InputTestSuite, "Parse Valid XML with two very simple empty tag roots, report only first root", "ValidElements", ParseValidXml, NULL, CleanUpXmlTestContext, &VerySimpleElementsOnly6Context);

AddTestCase (InputTestSuite, "Parse Valid XML with simple elements 3 layers", "ValidElements", ParseValidXml, NULL, CleanUpXmlTestContext, &SimpleElementsOnlyContext);
AddTestCase (InputTestSuite, "Parse Valid XML with 2 elements and 2 attributes", "ValidElementsAndAttributes", ParseValidXml, NULL, CleanUpXmlTestContext, &SimpleElementsAttributesContext);
AddTestCase (InputTestSuite, "Parse Invalid XML string containing an attribute with invalid xml chars", "NonXmlEncodedAttribute", ParseValidXml, NULL, CleanUpXmlTestContext, &NonEncodedXmlAttribute1Context);
Expand Down