Blob Blame History Raw
From 9deb46e363a341d8c243e4c85754e673b4b68571 Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phcoder@gmail.com>
Date: Tue, 20 Jan 2015 17:36:29 +0100
Subject: [PATCH 154/506] 	* grub-core/fs/btrfs.c: Avoid divisions by
 zero.

---
 ChangeLog            |  4 ++++
 grub-core/fs/btrfs.c | 35 +++++++++++++++++++++--------------
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a708ca2..8e38fdd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
 
+	* grub-core/fs/btrfs.c: Avoid divisions by zero.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
 	* grub-core/lib/pbkdf2.c (grub_crypto_pbkdf2): Check that hash len is not 0.
 
 2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 95a8fa6..9cffa91 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -680,6 +680,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
 	grub_uint64_t stripen;
 	grub_uint64_t stripe_offset;
 	grub_uint64_t off = addr - grub_le_to_cpu64 (key->offset);
+	grub_uint64_t chunk_stripe_length;
+	grub_uint16_t nstripes;
 	unsigned redundancy = 1;
 	unsigned i, j;
 
@@ -690,15 +692,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
 			       "couldn't find the chunk descriptor");
 	  }
 
+	nstripes = grub_le_to_cpu16 (chunk->nstripes) ? : 1;
+	chunk_stripe_length = grub_le_to_cpu64 (chunk->stripe_length) ? : 512;
 	grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
 		      "+0x%" PRIxGRUB_UINT64_T
 		      " (%d stripes (%d substripes) of %"
 		      PRIxGRUB_UINT64_T ")\n",
 		      grub_le_to_cpu64 (key->offset),
 		      grub_le_to_cpu64 (chunk->size),
-		      grub_le_to_cpu16 (chunk->nstripes),
+		      nstripes,
 		      grub_le_to_cpu16 (chunk->nsubstripes),
-		      grub_le_to_cpu64 (chunk->stripe_length));
+		      chunk_stripe_length);
 
 	switch (grub_le_to_cpu64 (chunk->type)
 		& ~GRUB_BTRFS_CHUNK_TYPE_BITS_DONTCARE)
@@ -708,8 +712,10 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
 	      grub_uint64_t stripe_length;
 	      grub_dprintf ("btrfs", "single\n");
 	      stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size),
-					     grub_le_to_cpu16 (chunk->nstripes),
+					     nstripes,
 					     NULL);
+	      if (stripe_length == 0)
+		stripe_length = 512;
 	      stripen = grub_divmod64 (off, stripe_length, &stripe_offset);
 	      csize = (stripen + 1) * stripe_length - off;
 	      break;
@@ -730,33 +736,34 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
 	      grub_uint64_t low;
 	      grub_dprintf ("btrfs", "RAID0\n");
 	      middle = grub_divmod64 (off,
-				      grub_le_to_cpu64 (chunk->stripe_length),
+				      chunk_stripe_length,
 				      &low);
 
-	      high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes),
+	      high = grub_divmod64 (middle, nstripes,
 				    &stripen);
 	      stripe_offset =
-		low + grub_le_to_cpu64 (chunk->stripe_length) * high;
-	      csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
+		low + chunk_stripe_length * high;
+	      csize = chunk_stripe_length - low;
 	      break;
 	    }
 	  case GRUB_BTRFS_CHUNK_TYPE_RAID10:
 	    {
 	      grub_uint64_t middle, high;
 	      grub_uint64_t low;
+	      grub_uint16_t nsubstripes;
+	      nsubstripes = grub_le_to_cpu16 (chunk->nsubstripes) ? : 1;
 	      middle = grub_divmod64 (off,
-				      grub_le_to_cpu64 (chunk->stripe_length),
+				      chunk_stripe_length,
 				      &low);
 
 	      high = grub_divmod64 (middle,
-				    grub_le_to_cpu16 (chunk->nstripes)
-				    / grub_le_to_cpu16 (chunk->nsubstripes),
+				    nstripes / nsubstripes ? : 1,
 				    &stripen);
-	      stripen *= grub_le_to_cpu16 (chunk->nsubstripes);
-	      redundancy = grub_le_to_cpu16 (chunk->nsubstripes);
-	      stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length)
+	      stripen *= nsubstripes;
+	      redundancy = nsubstripes;
+	      stripe_offset = low + chunk_stripe_length
 		* high;
-	      csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
+	      csize = chunk_stripe_length - low;
 	      break;
 	    }
 	  default:
-- 
2.4.3