OUT UINTN *ParsedBytes\r
)\r
{\r
- UINT16 DescriptorHeader;\r
- UINT8 Len;\r
- UINT8 *Ptr;\r
- UINTN Parsed;\r
+ USB_DESC_HEAD *Head;\r
+ UINTN Offset;\r
\r
- Parsed = 0;\r
- Ptr = Buffer;\r
+ //\r
+ // Total length is too small that cannot hold the single descriptor header plus data. \r
+ //\r
+ if (Length <= sizeof (USB_DESC_HEAD)) {\r
+ DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, total length = %d!\n", Length));\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
\r
- while (TRUE) {\r
+ //\r
+ // All the descriptor has a common LTV (Length, Type, Value)\r
+ // format. Skip the descriptor that isn't of this Type\r
+ //\r
+ Offset = 0;\r
+ Head = (USB_DESC_HEAD *)Buffer;\r
+ while (Offset < Length - sizeof (USB_DESC_HEAD)) {\r
//\r
- // Buffer length should not less than Desc length\r
+ // Above condition make sure Head->Len and Head->Type are safe to access\r
//\r
- if (Length < DescLength) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- DescriptorHeader = (UINT16) (*Ptr + ((*(Ptr + 1)) << 8));\r
-\r
- Len = Buffer[0];\r
+ Head = (USB_DESC_HEAD *)&Buffer[Offset];\r
\r
- //\r
- // Check to see if it is a start of expected descriptor\r
- //\r
- if (DescriptorHeader == ((DescType << 8) | DescLength)) {\r
- break;\r
+ if (Head->Len == 0) {\r
+ DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = 0!\n"));\r
+ return EFI_DEVICE_ERROR;\r
}\r
\r
- if ((UINT8) (DescriptorHeader >> 8) == DescType) {\r
- if (Len > DescLength) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
//\r
- // Descriptor length should be at least 2\r
- // and should not exceed the buffer length\r
+ // Make sure no overflow when adding Head->Len to Offset.\r
//\r
- if (Len < 2) {\r
+ if (Head->Len > MAX_UINTN - Offset) {\r
+ DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = %d!\n", Head->Len));\r
return EFI_DEVICE_ERROR;\r
}\r
\r
- if (Len > Length) {\r
- return EFI_DEVICE_ERROR;\r
+ if (Head->Type == DescType) {\r
+ break;\r
}\r
- //\r
- // Skip this mismatch descriptor\r
- //\r
- Length -= Len;\r
- Ptr += Len;\r
- Parsed += Len;\r
+\r
+ Offset += Head->Len;\r
+ }\r
+\r
+ //\r
+ // Head->Len is invalid resulting data beyond boundary, or\r
+ // Descriptor cannot be found: No such type.\r
+ //\r
+ if (Length < Offset) {\r
+ DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Offset/Len = %d/%d!\n", Offset, Length));\r
+ return EFI_DEVICE_ERROR;\r
}\r
\r
- *ParsedBytes = Parsed;\r
+ if ((Head->Type != DescType) || (Head->Len < DescLength)) {\r
+ DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head->Type, Head->Len));\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
\r
+ *ParsedBytes = Offset;\r
return EFI_SUCCESS;\r
}\r
\r