]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenVtf/GenVtf.c
BaseTools/GenVtf: silence false "stringop-overflow" warning with memcpy()
[mirror_edk2.git] / BaseTools / Source / C / GenVtf / GenVtf.c
index 60df34906eb804cab97ff26cddf6289787a92371..fc7ae02203ff9716133f65c46bab7401eb086dec 100644 (file)
@@ -1,6 +1,8 @@
-/**\r
+/** @file\r
+This file contains functions required to generate a boot strap file (BSF) also \r
+known as the Volume Top File (VTF)\r
 \r
-Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials are licensed and made available \r
 under the terms and conditions of the BSD License which accompanies this \r
 distribution.  The full text of the license may be found at\r
@@ -9,16 +11,6 @@ http://opensource.org/licenses/bsd-license.php
 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
-\r
-Module Name:\r
-\r
-  GenVtf.c\r
-\r
-Abstract:\r
-\r
-  This file contains functions required to generate a boot strap file (BSF)\r
-  also known as the Volume Top File (VTF)\r
-\r
 **/\r
 \r
 //\r
@@ -120,8 +112,8 @@ Returns:
 --*/\r
 {\r
   CHAR8  TemStr[5] = "0000";\r
-  unsigned Major;\r
-  unsigned Minor;\r
+  int    Major;\r
+  int    Minor;\r
   UINTN Length;\r
 \r
   Major = 0;\r
@@ -137,9 +129,9 @@ Returns:
   } else {\r
     Length = strlen(Str);\r
     if (Length < 4) {\r
-      strncpy (TemStr + 4 - Length, Str, Length);\r
+      memcpy (TemStr + 4 - Length, Str, Length);\r
     } else {\r
-      strncpy (TemStr, Str + Length - 4, 4);\r
+      memcpy (TemStr, Str + Length - 4, 4);\r
     }\r
   \r
     sscanf (\r
@@ -370,10 +362,20 @@ Returns:
       }\r
     } else if (strnicmp (*TokenStr, "COMP_BIN", 8) == 0) {\r
       TokenStr++;\r
-      strcpy (VtfInfo->CompBinName, *TokenStr);\r
+      if (strlen (*TokenStr) >= FILE_NAME_SIZE) {\r
+        Error (NULL, 0, 3000, "Invalid", "The 'COMP_BIN' name is too long.");\r
+        return ;\r
+      }\r
+      strncpy (VtfInfo->CompBinName, *TokenStr, FILE_NAME_SIZE - 1);\r
+      VtfInfo->CompBinName[FILE_NAME_SIZE - 1] = 0;\r
     } else if (strnicmp (*TokenStr, "COMP_SYM", 8) == 0) {\r
       TokenStr++;\r
-      strcpy (VtfInfo->CompSymName, *TokenStr);\r
+      if (strlen (*TokenStr) >= FILE_NAME_SIZE) {\r
+        Error (NULL, 0, 3000, "Invalid", "The 'COMP_SYM' name is too long.");\r
+        return ;\r
+      }\r
+      strncpy (VtfInfo->CompSymName, *TokenStr, FILE_NAME_SIZE - 1);\r
+      VtfInfo->CompSymName[FILE_NAME_SIZE - 1] = 0;\r
     } else if (strnicmp (*TokenStr, "COMP_SIZE", 9) == 0) {\r
       TokenStr++;\r
       if (strnicmp (*TokenStr, "-", 1) == 0) {\r
@@ -452,14 +454,24 @@ Returns:
     if (SectionOptionFlag) {\r
       if (stricmp (*TokenStr, "IA32_RST_BIN") == 0) {\r
         TokenStr++;\r
-        strcpy (IA32BinFile, *TokenStr);\r
+        if (strlen (*TokenStr) >= FILE_NAME_SIZE) {\r
+          Error (NULL, 0, 3000, "Invalid", "The 'IA32_RST_BIN' name is too long.");\r
+          break;\r
+        }\r
+        strncpy (IA32BinFile, *TokenStr, FILE_NAME_SIZE - 1);\r
+        IA32BinFile[FILE_NAME_SIZE - 1] = 0;\r
       }\r
     }\r
 \r
     if (SectionCompFlag) {\r
       if (stricmp (*TokenStr, "COMP_NAME") == 0) {\r
         TokenStr++;\r
-        strcpy (FileListPtr->CompName, *TokenStr);\r
+        if (strlen (*TokenStr) >= COMPONENT_NAME_SIZE) {\r
+          Error (NULL, 0, 3000, "Invalid", "The 'COMP_NAME' name is too long.");\r
+          break;\r
+        }\r
+        strncpy (FileListPtr->CompName, *TokenStr, COMPONENT_NAME_SIZE - 1);\r
+        FileListPtr->CompName[COMPONENT_NAME_SIZE - 1] = 0;\r
         TokenStr++;\r
         ParseAndUpdateComponents (FileListPtr);\r
       }\r
@@ -804,6 +816,7 @@ Returns:
 \r
   TmpFitPtr         = (FIT_TABLE *) RelativeAddress;\r
   NumFitComponents  = TmpFitPtr->CompSize;\r
+  *FitPtr           = NULL;\r
 \r
   for (Index = 0; Index < NumFitComponents; Index++) {\r
     if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_UNUSED) {\r
@@ -1069,6 +1082,7 @@ Returns:
   CHAR8   Buff4[10];\r
   CHAR8   Buff5[10];\r
   CHAR8   Token[50];\r
+  CHAR8   FormatString[MAX_LINE_LEN];\r
 \r
   Fp = fopen (LongFilePath (VtfInfo->CompSymName), "rb");\r
 \r
@@ -1077,10 +1091,25 @@ Returns:
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  //\r
+  // Generate the format string for fscanf\r
+  //\r
+  sprintf (\r
+    FormatString,\r
+    "%%%us %%%us %%%us %%%us %%%us %%%us %%%us",\r
+    (unsigned) sizeof (Buff1) - 1,\r
+    (unsigned) sizeof (Buff2) - 1,\r
+    (unsigned) sizeof (OffsetStr) - 1,\r
+    (unsigned) sizeof (Buff3) - 1,\r
+    (unsigned) sizeof (Buff4) - 1,\r
+    (unsigned) sizeof (Buff5) - 1,\r
+    (unsigned) sizeof (Token) - 1\r
+    );\r
+\r
   while (fgets (Buff, sizeof (Buff), Fp) != NULL) {\r
     fscanf (\r
       Fp,\r
-      "%s %s %s %s %s %s %s",\r
+      FormatString,\r
       Buff1,\r
       Buff2,\r
       OffsetStr,\r
@@ -1132,6 +1161,7 @@ Returns:
   EFI_ABORTED      - Aborted due to one of the many reasons like:\r
                       (a) Component Size greater than the specified size.\r
                       (b) Error opening files.\r
+                      (c) Fail to get the FIT table address.\r
 \r
   EFI_INVALID_PARAMETER     Value returned from call to UpdateEntryPoint()\r
   EFI_OUT_OF_RESOURCES      Memory allocation failure.\r
@@ -1170,6 +1200,7 @@ Returns:
 \r
   if (VtfInfo->PreferredSize) {\r
     if (FileSize > VtfInfo->CompSize) {\r
+      fclose (Fp);\r
       Error (NULL, 0, 2000, "Invalid parameter", "The component size is more than specified size.");\r
       return EFI_ABORTED;\r
     }\r
@@ -1179,6 +1210,7 @@ Returns:
 \r
   Buffer = malloc ((UINTN) FileSize);\r
   if (Buffer == NULL) {\r
+    fclose (Fp);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   memset (Buffer, 0, (UINTN) FileSize);\r
@@ -1238,18 +1270,25 @@ Returns:
     Vtf1TotalSize += (UINT32) (FileSize + NumAdjustByte);\r
     Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, FIRST_VTF);\r
   } else {\r
+    free (Buffer);\r
     Error (NULL, 0, 2000,"Invalid Parameter", "There's component in second VTF so second BaseAddress and Size must be specified!");\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   if (EFI_ERROR (Status)) {\r
+    free (Buffer);\r
     return EFI_ABORTED;\r
   }\r
 \r
   GetNextAvailableFitPtr (&CompFitPtr);\r
+  if (CompFitPtr == NULL) {\r
+    free (Buffer);\r
+    return EFI_ABORTED;\r
+  }\r
 \r
   CompFitPtr->CompAddress = CompStartAddress | IPF_CACHE_BIT;\r
   if ((FileSize % 16) != 0) {\r
+    free (Buffer);\r
     Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -1341,6 +1380,7 @@ Returns:
 \r
   FileSize = _filelength (fileno (Fp));\r
   if (FileSize < 64) {\r
+    fclose (Fp);\r
     Error (NULL, 0, 2000, "Invalid parameter", "PAL_A bin header is 64 bytes, so the Bin size must be larger than 64 bytes!");\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -1349,6 +1389,7 @@ Returns:
 \r
   if (VtfInfo->PreferredSize) {\r
     if (FileSize > VtfInfo->CompSize) {\r
+      fclose (Fp);\r
       Error (NULL, 0, 2000, "Invalid parameter", "The PAL_A Size is more than the specified size.");\r
       return EFI_ABORTED;\r
     }\r
@@ -1358,6 +1399,7 @@ Returns:
 \r
   Buffer = malloc ((UINTN) FileSize);\r
   if (Buffer == NULL) {\r
+    fclose (Fp);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   memset (Buffer, 0, (UINTN) FileSize);\r
@@ -1391,6 +1433,7 @@ Returns:
   PalFitPtr->CompAddress  = PalStartAddress | IPF_CACHE_BIT;\r
   //assert ((FileSize % 16) == 0);\r
   if ((FileSize % 16) != 0) {\r
+    free (Buffer);\r
     Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -1722,7 +1765,7 @@ Returns:
 \r
 --*/\r
 {\r
-  if ((BaseAddress >= 0) && (FwVolSize > 0x40) && ((BaseAddress + FwVolSize) % 8 == 0)) {\r
+  if ((FwVolSize > 0x40) && ((BaseAddress + FwVolSize) % 8 == 0)) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
@@ -1773,11 +1816,13 @@ Returns:
   FileSize = _filelength (fileno (Fp));\r
 \r
   if (FileSize > 16) {\r
+    fclose (Fp);\r
     return EFI_ABORTED;\r
   }\r
 \r
   Buffer = malloc (FileSize);\r
   if (Buffer == NULL) {\r
+    fclose (Fp);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
@@ -2189,6 +2234,7 @@ Returns:
   CHAR8   Section[MAX_LONG_FILE_PATH];\r
   CHAR8   Token[MAX_LONG_FILE_PATH];\r
   CHAR8   BaseToken[MAX_LONG_FILE_PATH];\r
+  CHAR8   FormatString[MAX_LINE_LEN];\r
   UINT64  TokenAddress;\r
   long    StartLocation;\r
 \r
@@ -2214,9 +2260,20 @@ Returns:
   //\r
   // Use the file name minus extension as the base for tokens\r
   //\r
-  strcpy (BaseToken, SourceFileName);\r
+  if (strlen (SourceFileName) >= MAX_LONG_FILE_PATH) {\r
+    fclose (SourceFile);\r
+    Error (NULL, 0, 2000, "Invalid parameter", "The source file name is too long.");\r
+    return EFI_ABORTED;\r
+  }\r
+  strncpy (BaseToken, SourceFileName, MAX_LONG_FILE_PATH - 1);\r
+  BaseToken[MAX_LONG_FILE_PATH - 1] = 0;\r
   strtok (BaseToken, ". \t\n");\r
-  strcat (BaseToken, "__");\r
+  if (strlen (BaseToken) + strlen ("__") >= MAX_LONG_FILE_PATH) {\r
+    fclose (SourceFile);\r
+    Error (NULL, 0, 2000, "Invalid parameter", "The source file name is too long.");\r
+    return EFI_ABORTED;\r
+  }\r
+  strncat (BaseToken, "__", MAX_LONG_FILE_PATH - strlen (BaseToken) - 1);\r
 \r
   //\r
   // Open the destination file\r
@@ -2266,6 +2323,18 @@ Returns:
     return EFI_ABORTED;\r
   }\r
 \r
+  //\r
+  // Generate the format string for fscanf\r
+  //\r
+  sprintf (\r
+    FormatString,\r
+    "%%%us | %%%us | %%%us | %%%us\n",\r
+    (unsigned) sizeof (Type) - 1,\r
+    (unsigned) sizeof (Address) - 1,\r
+    (unsigned) sizeof (Section) - 1,\r
+    (unsigned) sizeof (Token) - 1\r
+    );\r
+\r
   //\r
   // Read in the file\r
   //\r
@@ -2274,7 +2343,7 @@ Returns:
     //\r
     // Read a line\r
     //\r
-    if (fscanf (SourceFile, "%s | %s | %s | %s\n", Type, Address, Section, Token) == 4) {\r
+    if (fscanf (SourceFile, FormatString, Type, Address, Section, Token) == 4) {\r
 \r
       //\r
       // Get the token address\r
@@ -2546,6 +2615,12 @@ Returns:
       // Get the input VTF file name\r
       //\r
       VtfFileName = argv[Index+1];\r
+      if (VtfFP != NULL) {\r
+        //\r
+        // VTF file name has been given previously, override with the new value\r
+        //\r
+        fclose (VtfFP);\r
+      }\r
       VtfFP = fopen (LongFilePath (VtfFileName), "rb");\r
       if (VtfFP == NULL) {\r
         Error (NULL, 0, 0001, "Error opening file", VtfFileName);\r
@@ -2659,21 +2734,28 @@ Returns:
     }\r
     SymFileName = VTF_SYM_FILE;\r
   } else {\r
-    INTN OutFileNameLen = strlen(OutFileName1);\r
-    INTN Index;\r
+    INTN OutFileNameLen;\r
+    INTN NewIndex;\r
+\r
+    assert (OutFileName1);\r
+    OutFileNameLen = strlen(OutFileName1);\r
 \r
-    for (Index = OutFileNameLen; Index > 0; --Index) {\r
-      if (OutFileName1[Index] == '/' || OutFileName1[Index] == '\\') {\r
+    for (NewIndex = OutFileNameLen; NewIndex > 0; --NewIndex) {\r
+      if (OutFileName1[NewIndex] == '/' || OutFileName1[NewIndex] == '\\') {\r
         break;\r
       }\r
     }\r
-    if (Index == 0) {\r
+    if (NewIndex == 0) {\r
       SymFileName = VTF_SYM_FILE;\r
     } else {\r
-      INTN SymFileNameLen = Index + 1 + strlen(VTF_SYM_FILE);\r
+      INTN SymFileNameLen = NewIndex + 1 + strlen(VTF_SYM_FILE);\r
       SymFileName = malloc(SymFileNameLen + 1);\r
-      memcpy(SymFileName, OutFileName1, Index + 1);\r
-      memcpy(SymFileName + Index + 1, VTF_SYM_FILE, strlen(VTF_SYM_FILE));\r
+      if (SymFileName == NULL) {\r
+        Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+        goto ERROR;\r
+      }\r
+      memcpy(SymFileName, OutFileName1, NewIndex + 1);\r
+      memcpy(SymFileName + NewIndex + 1, VTF_SYM_FILE, strlen(VTF_SYM_FILE));\r
       SymFileName[SymFileNameLen] = '\0';\r
     }\r
     if (DebugMode) {\r