dp = dp0;
- while (1)
+ while (dp)
{
grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
&& subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
{
- grub_efi_uint16_t len;
- len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
- / sizeof (grub_efi_char16_t));
+ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
+
+ if (len < 4)
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
+ "malformed EFI Device Path node has length=%d", len);
+ return NULL;
+ }
+ len = (len - 4) / sizeof (grub_efi_char16_t);
filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 2;
}
if (!name)
return NULL;
- while (1)
+ while (dp)
{
grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
*p++ = '/';
- len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
- / sizeof (grub_efi_char16_t));
+ len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
+ if (len < 4)
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
+ "malformed EFI Device Path node has length=%d", len);
+ return NULL;
+ }
+
+ len = (len - 4) / sizeof (grub_efi_char16_t);
fp = (grub_efi_file_path_device_path_t *) dp;
/* According to EFI spec Path Name is NULL terminated */
while (len > 0 && fp->path_name[len - 1] == 0)
;
p = GRUB_EFI_NEXT_DEVICE_PATH (p))
{
- total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
+ grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (p);
+
+ /*
+ * In the event that we find a node that's completely garbage, for
+ * example if we get to 0x7f 0x01 0x02 0x00 ... (EndInstance with a size
+ * of 2), GRUB_EFI_END_ENTIRE_DEVICE_PATH() will be true and
+ * GRUB_EFI_NEXT_DEVICE_PATH() will return NULL, so we won't continue,
+ * and neither should our consumers, but there won't be any error raised
+ * even though the device path is junk.
+ *
+ * This keeps us from passing junk down back to our caller.
+ */
+ if (len < 4)
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
+ "malformed EFI Device Path node has length=%d", len);
+ return NULL;
+ }
+
+ total_size += len;
if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
break;
}
void
grub_efi_print_device_path (grub_efi_device_path_t *dp)
{
- while (1)
+ while (GRUB_EFI_DEVICE_PATH_VALID (dp))
{
grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
/* Return non-zero. */
return 1;
- while (1)
+ if (dp1 == dp2)
+ return 0;
+
+ while (GRUB_EFI_DEVICE_PATH_VALID (dp1) && GRUB_EFI_DEVICE_PATH_VALID (dp2))
{
grub_efi_uint8_t type1, type2;
grub_efi_uint8_t subtype1, subtype2;
dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
}
+ /*
+ * There's no "right" answer here, but we probably don't want to call a valid
+ * dp and an invalid dp equal, so pick one way or the other.
+ */
+ if (GRUB_EFI_DEVICE_PATH_VALID (dp1) && !GRUB_EFI_DEVICE_PATH_VALID (dp2))
+ return 1;
+ else if (!GRUB_EFI_DEVICE_PATH_VALID (dp1) && GRUB_EFI_DEVICE_PATH_VALID (dp2))
+ return -1;
+
return 0;
}
#define GRUB_EFI_DEVICE_PATH_TYPE(dp) ((dp)->type & 0x7f)
#define GRUB_EFI_DEVICE_PATH_SUBTYPE(dp) ((dp)->subtype)
#define GRUB_EFI_DEVICE_PATH_LENGTH(dp) ((dp)->length)
+#define GRUB_EFI_DEVICE_PATH_VALID(dp) ((dp) != NULL && GRUB_EFI_DEVICE_PATH_LENGTH (dp) >= 4)
/* The End of Device Path nodes. */
#define GRUB_EFI_END_DEVICE_PATH_TYPE (0xff & 0x7f)
#define GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE 0x01
#define GRUB_EFI_END_ENTIRE_DEVICE_PATH(dp) \
- (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \
- && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \
- == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE))
+ (!GRUB_EFI_DEVICE_PATH_VALID (dp) || \
+ (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \
+ && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \
+ == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)))
#define GRUB_EFI_NEXT_DEVICE_PATH(dp) \
- ((grub_efi_device_path_t *) ((char *) (dp) \
- + GRUB_EFI_DEVICE_PATH_LENGTH (dp)))
+ (GRUB_EFI_DEVICE_PATH_VALID (dp) \
+ ? ((grub_efi_device_path_t *) \
+ ((char *) (dp) + GRUB_EFI_DEVICE_PATH_LENGTH (dp))) \
+ : NULL)
/* Hardware Device Path. */
#define GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE 1