]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BaseLib/LinkedList.c
MdePkg/BaseSafeIntLib: fix undefined behavior in SafeInt64Add()
[mirror_edk2.git] / MdePkg / Library / BaseLib / LinkedList.c
index 03e8477c7eb8881d92fb4fbb44faf6cd73eeffcf..30fd7009e0078b98506f54431ebd116f62d01c7f 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Linked List Library Functions.\r
 \r
-  Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
 #include "BaseLibInternals.h"\r
 \r
 /**\r
-  Worker function that locates the Node in the List.\r
+  If PcdVerifyNodeInList is TRUE, ASSERTs when SecondEntry is or is not part of\r
+  the same doubly-linked list as FirstEntry depending on the value of InList.\r
+  Independent of PcdVerifyNodeInList, ASSERTs when FirstEntry is not part of a\r
+  valid list.\r
 \r
-  By searching the List, finds the location of the Node in List. At the same time,\r
-  verifies the validity of this list.\r
+  If FirstEntry is NULL, then ASSERT().\r
+  If FirstEntry->ForwardLink is NULL, then ASSERT().\r
+  If FirstEntry->BackLink is NULL, then ASSERT().\r
+  If PcdMaximumLinkedListLength is not zero, and List contains more than\r
+  PcdMaximumLinkedListLength nodes, then ASSERT().\r
+  If PcdVerifyNodeInList is TRUE and SecondEntry is NULL, then ASSERT().\r
+\r
+  @param  FirstEntry   A pointer to a node in a linked list.\r
+  @param  SecondEntry  A pointer to the node to locate.\r
+  @param  InList       Defines whether to check if SecondEntry is or is not part\r
+                       of the same doubly-linked list as FirstEntry.\r
+\r
+**/\r
+#if !defined (MDEPKG_NDEBUG)\r
+  #define ASSERT_VERIFY_NODE_IN_VALID_LIST(FirstEntry, SecondEntry, InList)  \\r
+    do {                                                                     \\r
+      if (FeaturePcdGet (PcdVerifyNodeInList)) {                             \\r
+        ASSERT (InList == IsNodeInList ((FirstEntry), (SecondEntry)));       \\r
+      } else {                                                               \\r
+        ASSERT (InternalBaseLibIsListValid (FirstEntry));                    \\r
+      }                                                                      \\r
+    } while (FALSE)\r
+#else\r
+  #define ASSERT_VERIFY_NODE_IN_VALID_LIST(FirstEntry, SecondEntry, InList)\r
+#endif\r
+\r
+/**\r
+  Worker function that verifies the validity of this list.\r
 \r
   If List is NULL, then ASSERT().\r
   If List->ForwardLink is NULL, then ASSERT().\r
-  If List->backLink is NULL, then ASSERT().\r
-  If Node is NULL, then ASSERT().\r
-  If PcdVerifyNodeInList is TRUE and DoMembershipCheck is TRUE and Node \r
-  is in not a member of List, then return FALSE\r
-  If PcdMaximumLinkedListLenth is not zero, and List contains more than\r
-  PcdMaximumLinkedListLenth nodes, then ASSERT().\r
+  If List->BackLink is NULL, then ASSERT().\r
+  If PcdMaximumLinkedListLength is not zero, and List contains more than\r
+  PcdMaximumLinkedListLength nodes, then ASSERT().\r
 \r
   @param  List              A pointer to a node in a linked list.\r
-  @param  Node              A pointer to a node in a linked list.\r
-  @param  VerifyNodeInList  TRUE if a check should be made to see if Node is a \r
-                            member of List.  FALSE if no membership test should \r
-                            be performed.\r
 \r
   @retval   TRUE if PcdVerifyNodeInList is FALSE\r
   @retval   TRUE if DoMembershipCheck is FALSE\r
 **/\r
 BOOLEAN\r
 EFIAPI\r
-InternalBaseLibIsNodeInList (\r
-  IN CONST LIST_ENTRY  *List,\r
-  IN CONST LIST_ENTRY  *Node,\r
-  IN BOOLEAN           VerifyNodeInList\r
+InternalBaseLibIsListValid (\r
+  IN CONST LIST_ENTRY  *List\r
   )\r
 {\r
   UINTN             Count;\r
@@ -60,40 +80,11 @@ InternalBaseLibIsNodeInList (
   ASSERT (List != NULL);\r
   ASSERT (List->ForwardLink != NULL);\r
   ASSERT (List->BackLink != NULL);\r
-  ASSERT (Node != NULL);\r
-\r
-  Count = 0;\r
-  Ptr   = List;\r
-\r
-  if (FeaturePcdGet (PcdVerifyNodeInList) && VerifyNodeInList) {\r
-    //\r
-    // Check to see if Node is a member of List.  \r
-    // Exit early if the number of nodes in List >= PcdMaximumLinkedListLength\r
-    //\r
-    do {\r
-      Ptr = Ptr->ForwardLink;\r
-      if (PcdGet32 (PcdMaximumLinkedListLength) > 0) {\r
-        Count++;\r
-        //\r
-        // ASSERT() if the linked list is too long\r
-        //\r
-        ASSERT (Count < PcdGet32 (PcdMaximumLinkedListLength));\r
-\r
-        //\r
-        // Return if the linked list is too long\r
-        //\r
-        if (Count >= PcdGet32 (PcdMaximumLinkedListLength)) {\r
-          return (BOOLEAN)(Ptr == Node);\r
-        }\r
-      }\r
-    } while ((Ptr != List) && (Ptr != Node)); \r
-\r
-    if (Ptr != Node) {\r
-      return FALSE;\r
-    }\r
-  }\r
 \r
   if (PcdGet32 (PcdMaximumLinkedListLength) > 0) {\r
+    Count = 0;\r
+    Ptr   = List;\r
+\r
     //\r
     // Count the total number of nodes in List.\r
     // Exit early if the number of nodes in List >= PcdMaximumLinkedListLength\r
@@ -104,14 +95,78 @@ InternalBaseLibIsNodeInList (
     } while ((Ptr != List) && (Count < PcdGet32 (PcdMaximumLinkedListLength)));\r
 \r
     //\r
-    // ASSERT() if the linked list is too long\r
+    // return whether linked list is too long\r
     //\r
-    ASSERT (Count < PcdGet32 (PcdMaximumLinkedListLength));\r
+    return (BOOLEAN)(Count < PcdGet32 (PcdMaximumLinkedListLength));\r
   }\r
 \r
   return TRUE;\r
 }\r
 \r
+/**\r
+  Checks whether FirstEntry and SecondEntry are part of the same doubly-linked\r
+  list.\r
+\r
+  If FirstEntry is NULL, then ASSERT().\r
+  If FirstEntry->ForwardLink is NULL, then ASSERT().\r
+  If FirstEntry->BackLink is NULL, then ASSERT().\r
+  If SecondEntry is NULL, then ASSERT();\r
+  If PcdMaximumLinkedListLength is not zero, and List contains more than\r
+  PcdMaximumLinkedListLength nodes, then ASSERT().\r
+\r
+  @param  FirstEntry   A pointer to a node in a linked list.\r
+  @param  SecondEntry  A pointer to the node to locate.\r
+\r
+  @retval TRUE   SecondEntry is in the same doubly-linked list as FirstEntry.\r
+  @retval FALSE  SecondEntry isn't in the same doubly-linked list as FirstEntry,\r
+                 or FirstEntry is invalid.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsNodeInList (\r
+  IN      CONST LIST_ENTRY      *FirstEntry,\r
+  IN      CONST LIST_ENTRY      *SecondEntry\r
+  )\r
+{\r
+  UINTN             Count;\r
+  CONST LIST_ENTRY  *Ptr;\r
+\r
+  //\r
+  // ASSERT List not too long\r
+  //\r
+  ASSERT (InternalBaseLibIsListValid (FirstEntry));\r
+\r
+  ASSERT (SecondEntry != NULL);\r
+\r
+  Count = 0;\r
+  Ptr   = FirstEntry;\r
+\r
+  //\r
+  // Check to see if SecondEntry is a member of FirstEntry.  \r
+  // Exit early if the number of nodes in List >= PcdMaximumLinkedListLength\r
+  //\r
+  do {\r
+    Ptr = Ptr->ForwardLink;\r
+    if (PcdGet32 (PcdMaximumLinkedListLength) > 0) {\r
+      Count++;\r
+\r
+      //\r
+      // Return if the linked list is too long\r
+      //\r
+      if (Count == PcdGet32 (PcdMaximumLinkedListLength)) {\r
+        return (BOOLEAN)(Ptr == SecondEntry);\r
+      }\r
+    }\r
+\r
+    if (Ptr == SecondEntry) {\r
+      return TRUE;\r
+    }\r
+  } while (Ptr != FirstEntry);\r
+\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Initializes the head node of a doubly-linked list, and returns the pointer to\r
   the head node of the doubly-linked list.\r
@@ -153,7 +208,7 @@ InitializeListHead (
   If Entry is NULL, then ASSERT().\r
   If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
   InitializeListHead(), then ASSERT().\r
-  If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number\r
+  If PcdMaximumLinkedListLength is not zero, and prior to insertion the number\r
   of nodes in ListHead, including the ListHead node, is greater than or\r
   equal to PcdMaximumLinkedListLength, then ASSERT().\r
 \r
@@ -174,7 +229,7 @@ InsertHeadList (
   //\r
   // ASSERT List not too long and Entry is not one of the nodes of List\r
   //\r
-  ASSERT (InternalBaseLibIsNodeInList (ListHead, Entry, FALSE));\r
+  ASSERT_VERIFY_NODE_IN_VALID_LIST (ListHead, Entry, FALSE);\r
   \r
   Entry->ForwardLink = ListHead->ForwardLink;\r
   Entry->BackLink = ListHead;\r
@@ -194,7 +249,7 @@ InsertHeadList (
   If Entry is NULL, then ASSERT().\r
   If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or \r
   InitializeListHead(), then ASSERT().\r
-  If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number\r
+  If PcdMaximumLinkedListLength is not zero, and prior to insertion the number\r
   of nodes in ListHead, including the ListHead node, is greater than or\r
   equal to PcdMaximumLinkedListLength, then ASSERT().\r
 \r
@@ -215,7 +270,7 @@ InsertTailList (
   //\r
   // ASSERT List not too long and Entry is not one of the nodes of List\r
   //\r
-  ASSERT (InternalBaseLibIsNodeInList (ListHead, Entry, FALSE));\r
+  ASSERT_VERIFY_NODE_IN_VALID_LIST (ListHead, Entry, FALSE);\r
   \r
   Entry->ForwardLink = ListHead;\r
   Entry->BackLink = ListHead->BackLink;\r
@@ -234,14 +289,14 @@ InsertTailList (
   If List is NULL, then ASSERT().\r
   If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or \r
   InitializeListHead(), then ASSERT().\r
-  If PcdMaximumLinkedListLenth is not zero, and the number of nodes\r
+  If PcdMaximumLinkedListLength is not zero, and the number of nodes\r
   in List, including the List node, is greater than or equal to\r
   PcdMaximumLinkedListLength, then ASSERT().\r
 \r
   @param  List  A pointer to the head node of a doubly-linked list.\r
 \r
   @return The first node of a doubly-linked list.\r
-  @retval NULL  The list is empty.\r
+  @retval List  The list is empty.\r
 \r
 **/\r
 LIST_ENTRY *\r
@@ -253,7 +308,7 @@ GetFirstNode (
   //\r
   // ASSERT List not too long\r
   //\r
-  ASSERT (InternalBaseLibIsNodeInList (List, List, FALSE));\r
+  ASSERT (InternalBaseLibIsListValid (List));\r
 \r
   return List->ForwardLink;\r
 }\r
@@ -269,8 +324,8 @@ GetFirstNode (
   If Node is NULL, then ASSERT().\r
   If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or \r
   InitializeListHead(), then ASSERT().\r
-  If PcdMaximumLinkedListLenth is not zero, and List contains more than\r
-  PcdMaximumLinkedListLenth nodes, then ASSERT().\r
+  If PcdMaximumLinkedListLength is not zero, and List contains more than\r
+  PcdMaximumLinkedListLength nodes, then ASSERT().\r
   If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT().\r
 \r
   @param  List  A pointer to the head node of a doubly-linked list.\r
@@ -289,7 +344,7 @@ GetNextNode (
   //\r
   // ASSERT List not too long and Node is one of the nodes of List\r
   //\r
-  ASSERT (InternalBaseLibIsNodeInList (List, Node, TRUE));\r
+  ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE);\r
 \r
   return Node->ForwardLink;\r
 }\r
@@ -305,8 +360,8 @@ GetNextNode (
   If Node is NULL, then ASSERT().\r
   If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or \r
   InitializeListHead(), then ASSERT().\r
-  If PcdMaximumLinkedListLenth is not zero, and List contains more than\r
-  PcdMaximumLinkedListLenth nodes, then ASSERT().\r
+  If PcdMaximumLinkedListLength is not zero, and List contains more than\r
+  PcdMaximumLinkedListLength nodes, then ASSERT().\r
   If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT().\r
  \r
   @param  List  A pointer to the head node of a doubly-linked list.\r
@@ -325,7 +380,7 @@ GetPreviousNode (
   //\r
   // ASSERT List not too long and Node is one of the nodes of List\r
   //\r
-  ASSERT (InternalBaseLibIsNodeInList (List, Node, TRUE));\r
+  ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE);\r
  \r
   return Node->BackLink;\r
 }\r
@@ -339,7 +394,7 @@ GetPreviousNode (
   If ListHead is NULL, then ASSERT().\r
   If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or \r
   InitializeListHead(), then ASSERT().\r
-  If PcdMaximumLinkedListLenth is not zero, and the number of nodes\r
+  If PcdMaximumLinkedListLength is not zero, and the number of nodes\r
   in List, including the List node, is greater than or equal to\r
   PcdMaximumLinkedListLength, then ASSERT().\r
 \r
@@ -358,7 +413,7 @@ IsListEmpty (
   //\r
   // ASSERT List not too long\r
   //\r
-  ASSERT (InternalBaseLibIsNodeInList (ListHead, ListHead, FALSE));\r
+  ASSERT (InternalBaseLibIsListValid (ListHead));\r
   \r
   return (BOOLEAN)(ListHead->ForwardLink == ListHead);\r
 }\r
@@ -376,7 +431,7 @@ IsListEmpty (
   If Node is NULL, then ASSERT().\r
   If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), \r
   then ASSERT().\r
-  If PcdMaximumLinkedListLenth is not zero, and the number of nodes\r
+  If PcdMaximumLinkedListLength is not zero, and the number of nodes\r
   in List, including the List node, is greater than or equal to\r
   PcdMaximumLinkedListLength, then ASSERT().\r
   If PcdVerifyNodeInList is TRUE and Node is not a node in List and Node is not \r
@@ -399,7 +454,7 @@ IsNull (
   //\r
   // ASSERT List not too long and Node is one of the nodes of List\r
   //\r
-  ASSERT (InternalBaseLibIsNodeInList (List, Node, TRUE));\r
+  ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE);\r
   \r
   return (BOOLEAN)(Node == List);\r
 }\r
@@ -415,7 +470,7 @@ IsNull (
   If Node is NULL, then ASSERT().\r
   If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
   InitializeListHead(), then ASSERT().\r
-  If PcdMaximumLinkedListLenth is not zero, and the number of nodes\r
+  If PcdMaximumLinkedListLength is not zero, and the number of nodes\r
   in List, including the List node, is greater than or equal to\r
   PcdMaximumLinkedListLength, then ASSERT().\r
   If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT().\r
@@ -437,7 +492,7 @@ IsNodeAtEnd (
   //\r
   // ASSERT List not too long and Node is one of the nodes of List\r
   //\r
-  ASSERT (InternalBaseLibIsNodeInList (List, Node, TRUE));\r
+  ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE);\r
   \r
   return (BOOLEAN)(!IsNull (List, Node) && List->BackLink == Node);\r
 }\r
@@ -484,7 +539,7 @@ SwapListEntries (
   //\r
   // ASSERT Entry1 and Entry2 are in the same linked list\r
   //\r
-  ASSERT (InternalBaseLibIsNodeInList (FirstEntry, SecondEntry, TRUE));\r
+  ASSERT_VERIFY_NODE_IN_VALID_LIST (FirstEntry, SecondEntry, TRUE);\r
   \r
   //\r
   // Ptr is the node pointed to by FirstEntry->ForwardLink\r