diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c
index 33fedf609b..269b2bda2e 100644
--- a/src/Common/Dlgcode.c
+++ b/src/Common/Dlgcode.c
@@ -7705,8 +7705,14 @@ CipherTestDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
if (lw == IDC_AUTO)
{
+ BOOL testsPassed;
WaitCursor ();
- if (!AutoTestAlgorithms())
+ testsPassed = AutoTestAlgorithms();
+ #if !defined(TC_WINDOWS_DRIVER) && !defined(_UEFI)
+ if (testsPassed && !XmlTest())
+ testsPassed = FALSE;
+ #endif
+ if (!testsPassed)
{
ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_SHOWNORMAL);
SetWindowTextW(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), GetString ("TESTS_FAILED"));
diff --git a/src/Common/Xml.c b/src/Common/Xml.c
index 357b7de183..a84bfa935f 100644
--- a/src/Common/Xml.c
+++ b/src/Common/Xml.c
@@ -84,16 +84,20 @@ char *XmlFindElementByAttributeValue (char *xml, char *nodeName, const char *att
char *XmlGetAttributeText (char *xmlNode, const char *xmlAttrName, char *xmlAttrValue, int xmlAttrValueSize)
{
char *t = xmlNode;
- char *e = xmlNode;
+ char *nodeEnd = xmlNode;
+ char *quote1, *quote2;
int l = 0;
+ if (xmlAttrValueSize <= 0)
+ return NULL;
+
xmlAttrValue[0] = 0;
if (t[0] != '<') return NULL;
- e = strchr (e, '>');
- if (e == NULL) return NULL;
+ nodeEnd = strchr (nodeEnd, '>');
+ if (nodeEnd == NULL) return NULL;
- while ((t = strstr (t, xmlAttrName)) && t < e)
+ while ((t = strstr (t, xmlAttrName)) && t < nodeEnd)
{
char *o = t + strlen (xmlAttrName);
if (t[-1] == ' '
@@ -108,12 +112,17 @@ char *XmlGetAttributeText (char *xmlNode, const char *xmlAttrName, char *xmlAttr
t++;
}
- if (t == NULL || t > e) return NULL;
+ if (t == NULL || t > nodeEnd) return NULL;
- t = ((char*)strchr (t, '"')) + 1;
- e = strchr (t, '"');
- l = (int)(e - t);
- if (e == NULL || l > xmlAttrValueSize) return NULL;
+ quote1 = strchr (t, '"');
+ if (quote1 == NULL || quote1 > nodeEnd) return NULL;
+ t = quote1 + 1;
+
+ quote2 = strchr (t, '"');
+ if (quote2 == NULL || quote2 > nodeEnd) return NULL;
+
+ l = (int)(quote2 - t);
+ if (l < 0 || l >= xmlAttrValueSize) return NULL;
memcpy (xmlAttrValue, t, l);
xmlAttrValue[l] = 0;
@@ -128,6 +137,9 @@ char *XmlGetNodeText (char *xmlNode, char *xmlText, int xmlTextSize)
char *e = xmlNode + 1;
int l = 0, i = 0, j = 0;
+ if (xmlTextSize <= 0)
+ return NULL;
+
xmlText[0] = 0;
if (t[0] != '<')
@@ -141,10 +153,16 @@ char *XmlGetNodeText (char *xmlNode, char *xmlText, int xmlTextSize)
if (e == NULL) return NULL;
l = (int)(e - t);
- if (e == NULL || l > xmlTextSize) return NULL;
+ if (l < 0) return NULL;
while (i < l)
{
+ if (j >= xmlTextSize - 1)
+ {
+ xmlText[0] = 0;
+ return NULL;
+ }
+
if (BeginsWith (&t[i], "<"))
{
xmlText[j++] = '<';
@@ -282,3 +300,69 @@ int XmlWriteFooter (FILE *file)
return fputws (L"\n", file);
}
#endif !defined(_UEFI)
+
+#if !defined(TC_WINDOWS_DRIVER) && !defined(_UEFI)
+BOOL XmlTest (void)
+{
+ char buffer[10];
+
+ /* XmlGetAttributeText tests */
+
+ /* 1. length size - 1 accepted */
+ char xmlAttrValid[] = "";
+ if (XmlGetAttributeText (xmlAttrValid, "attr", buffer, sizeof (buffer)) == NULL
+ || strcmp (buffer, "123456789") != 0)
+ return FALSE;
+
+ /* 2. length size rejected (off-by-one: would write NUL past buffer end) */
+ char xmlAttrOverflow[] = "";
+ if (XmlGetAttributeText (xmlAttrOverflow, "attr", buffer, sizeof (buffer)) != NULL)
+ return FALSE;
+
+ /* 3. malformed: closing quote absent returns NULL */
+ char xmlAttrMissingQuote[] = "";
+ if (XmlGetAttributeText (xmlAttrMissingQuote, "attr", buffer, sizeof (buffer)) != NULL)
+ return FALSE;
+
+ /* 4. closing quote belongs to a later tag, not the current one */
+ char xmlAttrCrossTag[] = "";
+ if (XmlGetAttributeText (xmlAttrCrossTag, "attr", buffer, sizeof (buffer)) != NULL)
+ return FALSE;
+
+
+ /* XmlGetNodeText tests */
+
+ /* 5. length size - 1 accepted */
+ char xmlNodeValid[] = "123456789";
+ if (XmlGetNodeText (xmlNodeValid, buffer, sizeof (buffer)) == NULL
+ || strcmp (buffer, "123456789") != 0)
+ return FALSE;
+
+ /* 6. length size rejected (off-by-one: would write NUL past buffer end) */
+ char xmlNodeOverflow[] = "1234567890";
+ if (XmlGetNodeText (xmlNodeOverflow, buffer, sizeof (buffer)) != NULL)
+ return FALSE;
+
+ /* 7. escaped text accepted: raw input is larger than buffer but decoded
+ output fits. Decoded: "<>&456789" (9 chars), buffer is 10 bytes. */
+ char xmlNodeEscaped[] = "<>&456789";
+ if (XmlGetNodeText (xmlNodeEscaped, buffer, sizeof (buffer)) == NULL
+ || strcmp (buffer, "<>&456789") != 0)
+ return FALSE;
+
+ /* 8. escaped text rejected: decoded output is exactly size (10 chars),
+ leaving no room for the NUL terminator. Decoded: "<>&4567890" (10 chars). */
+ char xmlNodeEscapedOverflow[] = "<>&4567890";
+ if (XmlGetNodeText (xmlNodeEscapedOverflow, buffer, sizeof (buffer)) != NULL)
+ return FALSE;
+
+ /* 9. seed the buffer and verify overflow failure leaves it empty */
+ char xmlNodeOverflowSeed[] = "1234567890";
+ buffer[0] = 's';
+ buffer[1] = 0;
+ if (XmlGetNodeText (xmlNodeOverflowSeed, buffer, sizeof (buffer)) != NULL || buffer[0] != 0)
+ return FALSE;
+
+ return TRUE;
+}
+#endif
diff --git a/src/Common/Xml.h b/src/Common/Xml.h
index 6a1daded7b..cc3d7b2f13 100644
--- a/src/Common/Xml.h
+++ b/src/Common/Xml.h
@@ -21,6 +21,10 @@ char *XmlGetNodeText (char *xmlNode, char *xmlText, int xmlTextSize);
char *XmlFindElementByAttributeValue (char *xml, char *nodeName, const char *attrName, const char *attrValue);
char *XmlQuoteText (const char *textSrc, char *textDst, int textDstMaxSize);
+#if !defined(TC_WINDOWS_DRIVER) && !defined(_UEFI)
+BOOL XmlTest (void);
+#endif
+
#if !defined(_UEFI)
wchar_t *XmlQuoteTextW(const wchar_t *textSrc, wchar_t *textDst, int textDstMaxSize);
int XmlWriteHeader (FILE *file);