summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2001-04-22 08:31:24 +0000
committerJim Meyering <jim@meyering.net>2001-04-22 08:31:24 +0000
commit519b707b4efbb3711adc24ad54a43f1474c42be3 (patch)
treee561c1a73cabb759b19e8aa791ee1ebc20c93083
parent2d0f3f2e74faf9bfb2d8d6462b86d515b50366c1 (diff)
downloadcoreutils-519b707b4efbb3711adc24ad54a43f1474c42be3.tar.xz
Fix bugs when computing length of large files.
Add overflow and write error checks. Use uint_fast32_t, not unsigned long, to do checksum calculation, as C99 says uint_fast32_t should be no slower and might be faster. Include <stdio.h> and "system.h" even if CRCTAB is defined, so that the code will compile if CRCTAB is defined. Include "human.h" if CRCTAB is not defined. (uint_fast32_t): Define if it appears that stdint.h didn't. (BIT, remainder, main, crctab): Use uint_fast32_t, not unsigned long, for checksums. (fill_r, remainder, main): Use ANSI prototypes. (fill_r, remainder, main): Omit duplicate code. (main): Use uintmax_t, not unsigned long, for file lengths. Use size_t, not long, for result of fread. Check for overflow when computing file lengths. Check for write error immediately after printing a line, so that we don't write to stdout indefinitely after an error.
-rw-r--r--src/cksum.c88
1 files changed, 47 insertions, 41 deletions
diff --git a/src/cksum.c b/src/cksum.c
index 043ee0264..95d4f5cd8 100644
--- a/src/cksum.c
+++ b/src/cksum.c
@@ -47,12 +47,17 @@
#define AUTHORS "Q. Frank Xia"
-#ifdef CRCTAB
+#include <stdio.h>
+#include "system.h"
+
+#if !defined UINT_FAST32_MAX && !defined uint_fast32_t
+# define uint_fast32_t unsigned int
+#endif
-# include <stdio.h>
+#ifdef CRCTAB
-# define BIT(x) ( (unsigned long)1 << (x) )
-# define SBIT BIT(31)
+# define BIT(x) ((uint_fast32_t) 1 << (x))
+# define SBIT BIT (31)
/* The generating polynomial is
@@ -61,47 +66,48 @@
The i bit in GEN is set if X^i is a summand of G(X) except X^32. */
-# define GEN (BIT(26)|BIT(23)|BIT(22)|BIT(16)|BIT(12)|BIT(11)|BIT(10)\
- |BIT(8) |BIT(7) |BIT(5) |BIT(4) |BIT(2) |BIT(1) |BIT(0));
+# define GEN (BIT (26) | BIT (23) | BIT (22) | BIT (16) | BIT (12) \
+ | BIT (11) | BIT (10) | BIT (8) | BIT (7) | BIT (5) \
+ | BIT (4) | BIT (2) | BIT (1) | BIT (0))
-static unsigned long r[8];
+static uint_fast32_t r[8];
static void
-fill_r ()
+fill_r (void)
{
int i;
r[0] = GEN;
for (i = 1; i < 8; i++)
- r[i] = (r[i - 1] & SBIT) ? (r[i - 1] << 1) ^ r[0] : r[i - 1] << 1;
+ r[i] = (r[i - 1] << 1) ^ ((r[i - 1] & SBIT) ? GEN : 0);
}
-static unsigned long
-remainder (m)
- int m;
+static uint_fast32_t
+remainder (int m)
{
- unsigned long rem = 0;
+ uint_fast32_t rem = 0;
int i;
for (i = 0; i < 8; i++)
if (BIT (i) & m)
- rem = rem ^ r[i];
+ rem ^= r[i];
return rem & 0xFFFFFFFF; /* Make it run on 64-bit machine. */
}
int
-main ()
+main (void)
{
int i;
fill_r ();
- printf ("unsigned long crctab[256] = {\n 0x0");
+ printf ("static uint_fast32_t crctab[256] =\n{\n 0x0");
for (i = 0; i < 51; i++)
{
printf (",\n 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X",
- remainder (i * 5 + 1), remainder (i * 5 + 2), remainder (i * 5 + 3),
- remainder (i * 5 + 4), remainder (i * 5 + 5));
+ remainder (i * 5 + 1), remainder (i * 5 + 2),
+ remainder (i * 5 + 3), remainder (i * 5 + 4),
+ remainder (i * 5 + 5));
}
printf ("\n};\n");
exit (EXIT_SUCCESS);
@@ -109,13 +115,12 @@ main ()
#else /* !CRCTAB */
-# include <stdio.h>
# include <getopt.h>
# include <sys/types.h>
-# include "system.h"
# include "closeout.h"
# include "long-options.h"
# include "error.h"
+# include "human.h"
/* Number of bytes to read at once. */
# define BUFLEN (1 << 16)
@@ -128,7 +133,7 @@ static struct option const long_options[] =
{0, 0, 0, 0}
};
-static unsigned long const crctab[256] =
+static uint_fast32_t crctab[256] =
{
0x0,
0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
@@ -196,10 +201,12 @@ static int
cksum (const char *file, int print_name)
{
unsigned char buf[BUFLEN];
- unsigned long crc = 0;
- long length = 0;
- long bytes_read;
+ uint_fast32_t crc = 0;
+ uintmax_t length = 0;
+ size_t bytes_read;
register FILE *fp;
+ char hbuf[LONGEST_HUMAN_READABLE + 1];
+ char *hp;
if (STREQ (file, "-"))
{
@@ -223,9 +230,11 @@ cksum (const char *file, int print_name)
{
unsigned char *cp = buf;
+ if (length + bytes_read < length)
+ error (EXIT_FAILURE, 0, _("%s: file too long"), file);
length += bytes_read;
while (bytes_read--)
- crc = (crc << 8) ^ crctab[((crc >> 24) ^ *(cp++)) & 0xFF];
+ crc = (crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
}
if (ferror (fp))
@@ -242,19 +251,20 @@ cksum (const char *file, int print_name)
return -1;
}
- bytes_read = length;
- while (bytes_read > 0)
- {
- crc = (crc << 8) ^ crctab[((crc >> 24) ^ bytes_read) & 0xFF];
- bytes_read >>= 8;
- }
+ hp = human_readable (length, hbuf, 1, 1);
+
+ for (; length; length >>= 8)
+ crc = (crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
crc = ~crc & 0xFFFFFFFF;
- printf ("%lu %ld", crc, length);
if (print_name)
- printf (" %s", file);
- putchar ('\n');
+ printf ("%u %s %s\n", (unsigned) crc, hp, file);
+ else
+ printf ("%u %s\n", (unsigned) crc, hp);
+
+ if (ferror (stdout))
+ error (EXIT_FAILURE, errno, "-: %s", _("write error"));
return 0;
}
@@ -313,16 +323,12 @@ main (int argc, char **argv)
}
}
- if (optind >= argc)
- {
- if (cksum ("-", 0) < 0)
- errors = 1;
- }
+ if (optind == argc)
+ errors |= cksum ("-", 0);
else
{
for (i = optind; i < argc; i++)
- if (cksum (argv[i], 1) < 0)
- errors = 1;
+ errors |= cksum (argv[i], 1);
}
if (have_read_stdin && fclose (stdin) == EOF)