diff -Naur grub-old/grub-core/fs/udf.c grub-new/grub-core/fs/udf.c
--- grub-old/grub-core/fs/udf.c	2010-10-28 17:14:51.001977447 +0200
+++ grub-new/grub-core/fs/udf.c	2010-10-28 16:54:11.079219549 +0200
@@ -336,6 +336,13 @@
   grub_uint8_t part_maps[1608];
 } __attribute__ ((packed));
 
+struct grub_udf_aed
+{
+  struct grub_udf_tag tag;
+  grub_uint32_t prev_ae;
+  grub_uint32_t ae_len;
+} __attribute__ ((packed));
+
 struct grub_udf_data
 {
   grub_disk_t disk;
@@ -406,8 +413,9 @@
 static grub_disk_addr_t
 grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
 {
+  char buf[U32 (node->data->lvd.bsize)];
   char *ptr;
-  int len;
+  grub_ssize_t len;
   grub_disk_addr_t filebytes;
 
   if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
@@ -415,22 +423,51 @@
       ptr = (char *) &node->fe.ext_attr[0] + U32 (node->fe.ext_attr_length);
       len = U32 (node->fe.alloc_descs_length);
     }
-  else
+  else if (U16 (node->fe.tag.tag_ident == GRUB_UDF_TAG_IDENT_EFE))
     {
       ptr = (char *) &node->efe.ext_attr[0] + U32 (node->efe.ext_attr_length);
       len = U32 (node->efe.alloc_descs_length);
     }
+  else
+    {
+      grub_error (GRUB_ERR_BAD_FS, "invalid file entry");
+      return 0;
+    }
 
   if ((U16 (node->fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK)
       == GRUB_UDF_ICBTAG_FLAG_AD_SHORT)
     {
       struct grub_udf_short_ad *ad = (struct grub_udf_short_ad *) ptr;
 
-      len /= sizeof (struct grub_udf_short_ad);
       filebytes = fileblock * U32 (node->data->lvd.bsize);
-      while (len > 0)
+      while (len >= (grub_ssize_t) sizeof (struct grub_udf_short_ad))
 	{
-	  if (filebytes < U32 (ad->length))
+	  grub_uint32_t adlen = U32 (ad->length) & 0x3fffffff;
+	  grub_uint32_t adtype = U32 (ad->length) >> 30;
+	  if (adtype == 3)
+	    {
+	      struct grub_udf_aed *extension;
+	      grub_disk_addr_t sec = grub_udf_get_block(node->data,
+							node->part_ref,
+							ad->position);
+	      if (grub_disk_read (node->data->disk, sec << node->data->lbshift,
+				  0, adlen, buf))
+		return 0;
+
+	      extension = (struct grub_udf_aed *) buf;
+	      if (U16 (extension->tag.tag_ident) != GRUB_UDF_TAG_IDENT_AED)
+		{
+		  grub_error (GRUB_ERR_BAD_FS, "invalid aed tag");
+		  return 0;
+		}
+
+	      len = U32 (extension->ae_len);
+	      ad = (struct grub_udf_short_ad *)
+		    (buf + sizeof (struct grub_udf_aed));
+	      continue;
+	    }
+
+	  if (filebytes < adlen)
 	    return ((U32 (ad->position) & GRUB_UDF_EXT_MASK) ? 0 :
                     (grub_udf_get_block (node->data,
                                          node->part_ref,
@@ -438,20 +475,44 @@
                      + (filebytes >> (GRUB_DISK_SECTOR_BITS
 				      + node->data->lbshift))));
 
-	  filebytes -= U32 (ad->length);
+	  filebytes -= adlen;
 	  ad++;
-	  len--;
+	  len -= sizeof (struct grub_udf_short_ad);
 	}
     }
   else
     {
       struct grub_udf_long_ad *ad = (struct grub_udf_long_ad *) ptr;
 
-      len /= sizeof (struct grub_udf_long_ad);
       filebytes = fileblock * U32 (node->data->lvd.bsize);
-      while (len > 0)
+      while (len >= (grub_ssize_t) sizeof (struct grub_udf_long_ad))
 	{
-	  if (filebytes < U32 (ad->length))
+	  grub_uint32_t adlen = U32 (ad->length) & 0x3fffffff;
+	  grub_uint32_t adtype = U32 (ad->length) >> 30;
+	  if (adtype == 3)
+	    {
+	      struct grub_udf_aed *extension;
+	      grub_disk_addr_t sec = grub_udf_get_block(node->data,
+							ad->block.part_ref,
+							ad->block.block_num);
+	      if (grub_disk_read (node->data->disk, sec << node->data->lbshift,
+				  0, adlen, buf))
+		return 0;
+
+	      extension = (struct grub_udf_aed *) buf;
+	      if (U16 (extension->tag.tag_ident) != GRUB_UDF_TAG_IDENT_AED)
+		{
+		  grub_error (GRUB_ERR_BAD_FS, "invalid aed tag");
+		  return 0;
+		}
+
+	      len = U32 (extension->ae_len);
+	      ad = (struct grub_udf_long_ad *)
+		    (buf + sizeof (struct grub_udf_aed));
+	      continue;
+	    }
+	      
+	  if (filebytes < adlen)
 	    return ((U32 (ad->block.block_num) & GRUB_UDF_EXT_MASK) ?  0 :
                     (grub_udf_get_block (node->data,
                                          ad->block.part_ref,
@@ -459,9 +520,9 @@
 		     + (filebytes >> (GRUB_DISK_SECTOR_BITS
 				      + node->data->lbshift))));
 
-	  filebytes -= U32 (ad->length);
+	  filebytes -= adlen;
 	  ad++;
-	  len--;
+	  len -= sizeof (struct grub_udf_long_ad);
 	}
     }
 
