From 94fef4e511d2b39590d9c5fa14c5ba7832465516 Mon Sep 17 00:00:00 2001
From: Alberto Bertogli <albertito@blitiri.com.ar>
Date: Sun, 8 Mar 2009 23:14:31 -0200
Subject: [PATCH 01/32] jfsck(): Check there's enough room for the checksum before computing it

Before computing the checksum in jfsck(), see if the file is long enough
to contain it. Otherwise, if the transaction file was truncated, we
would check the checksum anyways.

This is usually not a problem because the checksums shouldn't match, but
it's better to play safe. Also, it properly report such transactions as
broken instead of corrupt.

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>
---
 check.c |   22 +++++++++++++++++-----
 1 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/check.c b/check.c
index c430d14..cb4e854 100644
--- a/check.c
+++ b/check.c
@@ -23,11 +23,12 @@
 
 
 /* fill a transaction structure from a mmapped transaction file */
-static int fill_trans(unsigned char *map, off_t len, struct jtrans *ts)
+static off_t fill_trans(unsigned char *map, off_t len, struct jtrans *ts)
 {
 	int i;
 	unsigned char *p;
 	struct joper *op, *tmp;
+	off_t translen;
 
 	if (len < J_DISKHEADSIZE)
 		return 0;
@@ -43,6 +44,8 @@ static int fill_trans(unsigned char *map, off_t len, struct jtrans *ts)
 	ts->numops = *( (uint32_t *) p);
 	p += 4;
 
+	translen = J_DISKHEADSIZE;
+
 	for (i = 0; i < ts->numops; i++) {
 		if (p + J_DISKOPHEADSIZE > map + len)
 			goto error;
@@ -79,9 +82,11 @@ static int fill_trans(unsigned char *map, off_t len, struct jtrans *ts)
 			op->prev = tmp;
 			op->next = NULL;
 		}
+
+		translen += J_DISKOPHEADSIZE + op->len;
 	}
 
-	return 1;
+	return translen;
 
 error:
 	while (ts->op != NULL) {
@@ -106,7 +111,7 @@ int jfsck(const char *name, const char *jdir, struct jfsck_result *res)
 	DIR *dir;
 	struct dirent *dent;
 	unsigned char *map;
-	off_t filelen, lr;
+	off_t filelen, translen, lr;
 
 	tfd = -1;
 	filelen = 0;
@@ -250,8 +255,15 @@ int jfsck(const char *name, const char *jdir, struct jfsck_result *res)
 			map = NULL;
 			goto loop;
 		}
-		rv = fill_trans(map, filelen, curts);
-		if (rv != 1) {
+		translen = fill_trans(map, filelen, curts);
+		if (translen == 0) {
+			res->broken++;
+			goto loop;
+		}
+
+		/* see if there's enough room for the checksum after the
+		 * transaction information */
+		if (filelen != translen + sizeof(uint32_t)) {
 			res->broken++;
 			goto loop;
 		}
-- 
1.6.2.rc0.226.gf08f


