]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
Fix bugs when computing length of large files.
authorJim Meyering <jim@meyering.net>
Sun, 22 Apr 2001 08:31:24 +0000 (08:31 +0000)
committerJim Meyering <jim@meyering.net>
Sun, 22 Apr 2001 08:31:24 +0000 (08:31 +0000)
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.

src/cksum.c

index 043ee026419191c0ab2c4d814740dd168a8a9caa..95d4f5cd859bc3ff5ce2842d64dbd5ffbd1ac0f7 100644 (file)
 
 #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
 
 
   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)