]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
ShellPkg: acpiview: GTDT: Prevent buffer overruns
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Gtdt / GtdtParser.c
index 1e5b5764f50a2d29aa904c889bc89af5bdc3af5c..57174e14c80072f12b90e1996ebe8f0002d0c404 100644 (file)
@@ -23,7 +23,6 @@ STATIC CONST UINT8*  PlatformTimerType;
 STATIC CONST UINT16* PlatformTimerLength;\r
 STATIC CONST UINT32* GtBlockTimerCount;\r
 STATIC CONST UINT32* GtBlockTimerOffset;\r
-STATIC CONST UINT16* GtBlockLength;\r
 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
 \r
 /**\r
@@ -127,7 +126,7 @@ STATIC CONST ACPI_PARSER GtPlatformTimerHeaderParser[] = {
 **/\r
 STATIC CONST ACPI_PARSER GtBlockParser[] = {\r
   {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL},\r
-  {L"Length", 2, 1, L"%d", NULL, (VOID**)&GtBlockLength, NULL, NULL},\r
+  {L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL},\r
   {L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL},\r
   {L"Physical address (CntCtlBase)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL},\r
   {L"Timer Count", 4, 12, L"%d", NULL, (VOID**)&GtBlockTimerCount,\r
@@ -168,56 +167,43 @@ STATIC CONST ACPI_PARSER SBSAGenericWatchdogParser[] = {
 /**\r
   This function parses the Platform GT Block.\r
 \r
-  @param [in] Ptr     Pointer to the start of the GT Block data.\r
-  @param [in] Length  Length of the GT Block structure.\r
+  @param [in] Ptr       Pointer to the start of the GT Block data.\r
+  @param [in] Length    Length of the GT Block structure.\r
 **/\r
 STATIC\r
 VOID\r
 DumpGTBlock (\r
   IN UINT8* Ptr,\r
-  IN UINT32 Length\r
+  IN UINT16 Length\r
   )\r
 {\r
   UINT32 Index;\r
   UINT32 Offset;\r
-  UINT32 GTBlockTimerLength;\r
-\r
-  Offset = ParseAcpi (\r
-             TRUE,\r
-             2,\r
-             "GT Block",\r
-             Ptr,\r
-             Length,\r
-             PARSER_PARAMS (GtBlockParser)\r
-             );\r
-  GTBlockTimerLength = (*GtBlockLength - Offset) / (*GtBlockTimerCount);\r
-  Length -= Offset;\r
-\r
-  if (*GtBlockTimerCount != 0) {\r
-    Ptr += (*GtBlockTimerOffset);\r
-    Index = 0;\r
-    while ((Index < (*GtBlockTimerCount)) && (Length >= GTBlockTimerLength)) {\r
-      Offset = ParseAcpi (\r
-                 TRUE,\r
-                 2,\r
-                 "GT Block Timer",\r
-                 Ptr,\r
-                 GTBlockTimerLength,\r
-                 PARSER_PARAMS (GtBlockTimerParser)\r
-                 );\r
-      // Increment by GT Block Timer structure size\r
-      Ptr += Offset;\r
-      Length -= Offset;\r
-      Index++;\r
-    }\r
 \r
-    if (Length != 0) {\r
-      IncrementErrorCount ();\r
-      Print (\r
-        L"ERROR:GT Block Timer length mismatch. Unparsed %d bytes.\n",\r
-        Length\r
-        );\r
-    }\r
+  ParseAcpi (\r
+    TRUE,\r
+    2,\r
+    "GT Block",\r
+    Ptr,\r
+    Length,\r
+    PARSER_PARAMS (GtBlockParser)\r
+    );\r
+\r
+  Offset = *GtBlockTimerOffset;\r
+  Index = 0;\r
+\r
+  // Parse the specified number of GT Block Timer Structures or the GT Block\r
+  // Structure buffer length. Whichever is minimum.\r
+  while ((Index++ < *GtBlockTimerCount) &&\r
+         (Offset < Length)) {\r
+    Offset += ParseAcpi (\r
+                TRUE,\r
+                2,\r
+                "GT Block Timer",\r
+                Ptr + Offset,\r
+                Length - Offset,\r
+                PARSER_PARAMS (GtBlockTimerParser)\r
+                );\r
   }\r
 }\r
 \r
@@ -270,6 +256,7 @@ ParseAcpiGtdt (
   )\r
 {\r
   UINT32 Index;\r
+  UINT32 Offset;\r
   UINT8* TimerPtr;\r
 \r
   if (!Trace) {\r
@@ -285,36 +272,54 @@ ParseAcpiGtdt (
     PARSER_PARAMS (GtdtParser)\r
     );\r
 \r
-  if (*GtdtPlatformTimerCount != 0) {\r
-    TimerPtr = Ptr + (*GtdtPlatformTimerOffset);\r
-    Index = 0;\r
-    do {\r
-      // Parse the Platform Timer Header\r
-      ParseAcpi (\r
-        FALSE,\r
-        0,\r
-        NULL,\r
-        TimerPtr,\r
-        4,  // GT Platform Timer structure header length.\r
-        PARSER_PARAMS (GtPlatformTimerHeaderParser)\r
+  TimerPtr = Ptr + *GtdtPlatformTimerOffset;\r
+  Offset = *GtdtPlatformTimerOffset;\r
+  Index = 0;\r
+\r
+  // Parse the specified number of Platform Timer Structures or the GTDT\r
+  // buffer length. Whichever is minimum.\r
+  while ((Index++ < *GtdtPlatformTimerCount) &&\r
+         (Offset < AcpiTableLength)) {\r
+    // Parse the Platform Timer Header to obtain Length and Type\r
+    ParseAcpi (\r
+      FALSE,\r
+      0,\r
+      NULL,\r
+      TimerPtr,\r
+      AcpiTableLength - Offset,\r
+      PARSER_PARAMS (GtPlatformTimerHeaderParser)\r
+      );\r
+\r
+    // Make sure the Platform Timer is inside the table.\r
+    if ((Offset + *PlatformTimerLength) > AcpiTableLength) {\r
+      IncrementErrorCount ();\r
+      Print (\r
+        L"ERROR: Invalid Platform Timer Structure length. " \\r
+          L"PlatformTimerLength = %d. RemainingTableBufferLength = %d. " \\r
+          L"GTDT parsing aborted.\n",\r
+        *PlatformTimerLength,\r
+        AcpiTableLength - Offset\r
         );\r
-      switch (*PlatformTimerType) {\r
-        case EFI_ACPI_6_2_GTDT_GT_BLOCK:\r
-          DumpGTBlock (TimerPtr, *PlatformTimerLength);\r
-          break;\r
-        case EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG:\r
-          DumpWatchdogTimer (TimerPtr, *PlatformTimerLength);\r
-          break;\r
-        default:\r
-          IncrementErrorCount ();\r
-          Print (\r
-            L"ERROR: INVALID Platform Timer Type = %d\n",\r
-            *PlatformTimerType\r
-            );\r
-          break;\r
-      } // switch\r
-      TimerPtr += (*PlatformTimerLength);\r
-      Index++;\r
-    } while (Index < *GtdtPlatformTimerCount);\r
-  }\r
+      return;\r
+    }\r
+\r
+    switch (*PlatformTimerType) {\r
+      case EFI_ACPI_6_3_GTDT_GT_BLOCK:\r
+        DumpGTBlock (TimerPtr, *PlatformTimerLength);\r
+        break;\r
+      case EFI_ACPI_6_3_GTDT_SBSA_GENERIC_WATCHDOG:\r
+        DumpWatchdogTimer (TimerPtr, *PlatformTimerLength);\r
+        break;\r
+      default:\r
+        IncrementErrorCount ();\r
+        Print (\r
+          L"ERROR: Invalid Platform Timer Type = %d\n",\r
+          *PlatformTimerType\r
+          );\r
+        break;\r
+    } // switch\r
+\r
+    TimerPtr += *PlatformTimerLength;\r
+    Offset += *PlatformTimerLength;\r
+  } // while\r
 }\r