bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: integer overflow in /bin/ls


From: Paul Eggert
Subject: Re: integer overflow in /bin/ls
Date: 13 Oct 2003 00:54:04 -0700
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3

Georgi Guninski <address@hidden> writes:

> The heap is quite screwed, but ls is killed by the kernel due to
> memory usage.

Thanks for reporting the bug.  As it happens, I had already been
preparing a more general patch for address arithmetic overflow bugs in
coreutils.  A patch for the 'ls' problem is enclosed below.  It causes
'ls' to immediately report "memory exhausted" for your example.  It
also fixes a few other related bugs (notably on 64-bit hosts).

> Probably ls should not accept big ints after -w.

'ls' could impose an arbitrary limit on column width, but that would
run counter to the "no arbitrary limits" policy of GNU.

> As a side effect this causes temporary DoS in wu-ftpd.

Perhaps wu-ftpd can refuse to invoke 'ls' with the -w option, or with
a -w option that wu-ftpd thinks would use too much memory.


2003-10-13  Paul Eggert  <address@hidden>

        Fix address-arithmetic bug in 'ls', reported by Georgi Guninski.
        Remove several arbitrary limits on hosts where int cannot represent
        all size_t values.

        * lib/xalloc.h, lib/xmalloc.h, lib/xstrdup.c, m4/xalloc.m4:
        Import latest version from gnulib.
        * src/ls.c (struct bin_str.len, length_of_file_name_and_frills, indent,
        nfiles, files_index, tabsize, line_length, struct column_info.line_len,
        struct column_info.col_arr[0], max_idx):
        Now size_t, not int.
        (get_funky_string): Return bool indicating success, instead of
        a negative count to indicate failure.  Store number of columns
        through new parameter OUTPUT_COUNT; that way, they can never
        go negative.  Change equals_end from int to bool.  All uses
        changed.
        (struct column_info.valid_len): Now bool, not int.  All uses changed.
        (dired_dump_obstack, get_funky_string, clear_files,
        extract_dirs_from_files, print_current_files,
        print_many_per_line, print_horizontal, init_column_info,
        put_indicator, length_of_file_name_and_frills,
        print_with_commas): Use size_t, not int, for local variables
        that count sizes.
        (decode_switches): Decode sizes using xstrtoul, not xstrtol.
        Check for TIOCGWINSZ returing negative values (or values greater
        than SIZE_MAX!).
        (visit_dir, main, parse_ls_color, queue_directory, add_ignore_pattern,
        init_column_info):
        Use xmalloc and xnmalloc, not XMALLOC.
        (gobble_file): Use xnrealloc, not XREALLOC.
        (print_color_indicator): Remove now-unnecessary cast to size_t.

Index: lib/xalloc.h
===================================================================
RCS file: /cvsroot/coreutils/coreutils/lib/xalloc.h,v
retrieving revision 1.19
diff -p -u -r1.19 xalloc.h
--- lib/xalloc.h        23 Jul 2003 05:38:36 -0000      1.19
+++ lib/xalloc.h        13 Oct 2003 07:36:58 -0000
@@ -48,31 +48,23 @@ extern char const xalloc_msg_memory_exha
    memory allocation failure.  */
 extern void xalloc_die (void) ATTRIBUTE_NORETURN;
 
-void *xmalloc (size_t n);
+void *xmalloc (size_t s);
+void *xnmalloc (size_t n, size_t s);
+void *xzalloc (size_t s);
 void *xcalloc (size_t n, size_t s);
-void *xrealloc (void *p, size_t n);
+void *xrealloc (void *p, size_t s);
+void *xnrealloc (void *p, size_t n, size_t s);
+void *xclone (void const *p, size_t s);
 char *xstrdup (const char *str);
 
-# define XMALLOC(Type, N_items) xmalloc (sizeof (Type) * (N_items))
-# define XCALLOC(Type, N_items) xcalloc (sizeof (Type), N_items)
-# define XREALLOC(Ptr, Type, N_items) xrealloc (Ptr, sizeof (Type) * (N_items))
-
-/* Declare and alloc memory for VAR of type TYPE. */
-# define NEW(Type, Var)  Type *(Var) = XMALLOC (Type, 1)
-
-/* Free VAR only if non NULL. */
-# define XFREE(Var)    \
-   do {                 \
-      if (Var)          \
-        free (Var);     \
-   } while (0)
-
-/* Return a pointer to a malloc'ed copy of the array SRC of NUM elements. */
-# define CCLONE(Src, Num) \
-  (memcpy (xmalloc (sizeof *(Src) * (Num)), Src, sizeof *(Src) * (Num)))
-
-/* Return a malloc'ed copy of SRC. */
-# define CLONE(Src) CCLONE (Src, 1)
-
+/* These macros are deprecated; they will go away soon, and are retained
+   temporarily only to ease conversion to the functions described above.  */
+# define CCLONE(p, n) xclone (p, (n) * sizeof *(p))
+# define CLONE(p) xclone (p, sizeof *(p))
+# define NEW(type, var) type *var = xmalloc (sizeof (type))
+# define XCALLOC(type, n) xcalloc (n, sizeof (type))
+# define XMALLOC(type, n) xnmalloc (n, sizeof (type))
+# define XREALLOC(p, type, n) xnrealloc (p, n, sizeof (type))
+# define XFREE(p) free (p)
 
 #endif /* !XALLOC_H_ */
Index: lib/xmalloc.c
===================================================================
RCS file: /cvsroot/coreutils/coreutils/lib/xmalloc.c,v
retrieving revision 1.26
diff -p -u -r1.26 xmalloc.c
--- lib/xmalloc.c       13 Sep 2003 10:23:46 -0000      1.26
+++ lib/xmalloc.c       13 Oct 2003 07:36:58 -0000
@@ -23,6 +23,7 @@
 
 #include "xalloc.h"
 
+#include <stdbool.h>
 #include <stdlib.h>
 
 #include "gettext.h"
@@ -30,10 +31,11 @@
 #define N_(msgid) msgid
 
 #include "error.h"
-#include "exit.h"
 #include "exitfail.h"
 
-/* The following tests require AC_PREREQ(2.54).  */
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
 
 #ifndef HAVE_MALLOC
 "you must run the autoconf test for a GNU libc compatible malloc"
@@ -46,6 +48,15 @@
 /* If non NULL, call this function when memory is exhausted. */
 void (*xalloc_fail_func) (void) = 0;
 
+/* Return true if array of N objects, each of size S, cannot exist due
+   to arithmetic overflow.  S must be nonzero.  */
+
+static inline bool
+array_size_overflow (size_t n, size_t s)
+{
+  return SIZE_MAX / s < n;
+}
+
 /* If XALLOC_FAIL_FUNC is NULL, or does return, display this message
    before exiting when memory is exhausted.  Goes through gettext. */
 char const xalloc_msg_memory_exhausted[] = N_("memory exhausted");
@@ -58,8 +69,20 @@ xalloc_die (void)
   error (exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted));
   /* The `noreturn' cannot be given to error, since it may return if
      its first argument is 0.  To help compilers understand the
-     xalloc_die does terminate, call exit. */
-  exit (EXIT_FAILURE);
+     xalloc_die does terminate, call abort.  */
+  abort ();
+}
+
+/* Allocate an array of N objects, each with S bytes of memory,
+   dynamically, with error checking.  S must be nonzero.  */
+
+inline void *
+xnmalloc (size_t n, size_t s)
+{
+  void *p;
+  if (array_size_overflow (n, s) || ! (p = malloc (n * s)))
+    xalloc_die ();
+  return p;
 }
 
 /* Allocate N bytes of memory dynamically, with error checking.  */
@@ -67,10 +90,16 @@ xalloc_die (void)
 void *
 xmalloc (size_t n)
 {
-  void *p;
+  return xnmalloc (n, 1);
+}
+
+/* Change the size of an allocated block of memory P to an array of N
+   objects each of S bytes, with error checking.  S must be nonzero.  */
 
-  p = malloc (n);
-  if (p == 0)
+inline void *
+xnrealloc (void *p, size_t n, size_t s)
+{
+  if (array_size_overflow (n, s) || ! (p = realloc (p, n * s)))
     xalloc_die ();
   return p;
 }
@@ -81,21 +110,39 @@ xmalloc (size_t n)
 void *
 xrealloc (void *p, size_t n)
 {
-  p = realloc (p, n);
-  if (p == 0)
-    xalloc_die ();
-  return p;
+  return xnrealloc (p, n, 1);
+}
+
+/* Allocate S bytes of zeroed memory dynamically, with error checking.
+   There's no need for xnzalloc (N, S), since it would be equivalent
+   to xcalloc (N, S).  */
+
+void *
+xzalloc (size_t s)
+{
+  return memset (xmalloc (s), 0, s);
 }
 
-/* Allocate memory for N elements of S bytes, with error checking.  */
+/* Allocate zeroed memory for N elements of S bytes, with error
+   checking.  S must be nonzero.  */
 
 void *
 xcalloc (size_t n, size_t s)
 {
   void *p;
-
-  p = calloc (n, s);
-  if (p == 0)
+  /* Test for overflow, since some calloc implementations don't have
+     proper overflow checks.  */
+  if (array_size_overflow (n, s) || ! (p = calloc (n, s)))
     xalloc_die ();
   return p;
+}
+
+/* Clone an object P of size S, with error checking.  There's no need
+   for xnclone (P, N, S), since xclone (P, N * S) works without any
+   need for an arithmetic overflow check.  */
+
+void *
+xclone (void const *p, size_t s)
+{
+  return memcpy (xmalloc (s), p, s);
 }
Index: lib/xstrdup.c
===================================================================
RCS file: /cvsroot/coreutils/coreutils/lib/xstrdup.c,v
retrieving revision 1.9
diff -p -u -r1.9 xstrdup.c
--- lib/xstrdup.c       13 Sep 2003 22:01:20 -0000      1.9
+++ lib/xstrdup.c       13 Oct 2003 07:36:58 -0000
@@ -29,5 +29,5 @@
 char *
 xstrdup (const char *string)
 {
-  return strcpy (xmalloc (strlen (string) + 1), string);
+  return xclone (string, strlen (string) + 1);
 }
Index: m4/xalloc.m4
===================================================================
RCS file: /cvsroot/coreutils/coreutils/m4/xalloc.m4,v
retrieving revision 1.2
diff -p -u -r1.2 xalloc.m4
--- m4/xalloc.m4        13 Sep 2003 10:47:43 -0000      1.2
+++ m4/xalloc.m4        13 Oct 2003 07:36:59 -0000
@@ -1,4 +1,4 @@
-# xalloc.m4 serial 3
+# xalloc.m4 serial 4
 dnl Copyright (C) 2002-2003 Free Software Foundation, Inc.
 dnl This file is free software, distributed under the terms of the GNU
 dnl General Public License.  As a special exception to the GNU General
@@ -14,8 +14,10 @@ AC_DEFUN([gl_XALLOC],
 
 # Prerequisites of lib/xmalloc.c.
 AC_DEFUN([gl_PREREQ_XMALLOC], [
+  AC_REQUIRE([AC_C_INLINE])
   AC_REQUIRE([jm_FUNC_MALLOC])
   AC_REQUIRE([jm_FUNC_REALLOC])
+  :
 ])
 
 # Prerequisites of lib/xstrdup.c.
Index: src/ls.c
===================================================================
RCS file: /cvsroot/coreutils/coreutils/src/ls.c,v
retrieving revision 1.339
diff -p -u -r1.339 ls.c
--- src/ls.c    28 Sep 2003 08:22:35 -0000      1.339
+++ src/ls.c    13 Oct 2003 07:42:37 -0000
@@ -234,7 +234,7 @@ struct fileinfo
 
 struct bin_str
   {
-    int len;                   /* Number of bytes */
+    size_t len;                        /* Number of bytes */
     const char *string;                /* Pointer to the same */
   };
 
@@ -256,14 +256,14 @@ static uintmax_t gobble_file (const char
 static void print_color_indicator (const char *name, mode_t mode, int linkok);
 static void put_indicator (const struct bin_str *ind);
 static int put_indicator_direct (const struct bin_str *ind);
-static int length_of_file_name_and_frills (const struct fileinfo *f);
+static size_t length_of_file_name_and_frills (const struct fileinfo *f);
 static void add_ignore_pattern (const char *pattern);
 static void attach (char *dest, const char *dirname, const char *name);
 static void clear_files (void);
 static void extract_dirs_from_files (const char *dirname,
                                     int ignore_dot_and_dot_dot);
 static void get_link_name (const char *filename, struct fileinfo *f);
-static void indent (int from, int to);
+static void indent (size_t from, size_t to);
 static void init_column_info (void);
 static void print_current_files (void);
 static void print_dir (const char *name, const char *realname);
@@ -310,10 +310,10 @@ static Hash_table *active_dir_set;
 static struct fileinfo *files;  /* FIXME: rename this to e.g. cwd_file */
 
 /* Length of block that `files' points to, measured in files.  */
-static int nfiles;  /* FIXME: rename this to e.g. cwd_n_alloc */
+static size_t nfiles;  /* FIXME: rename this to e.g. cwd_n_alloc */
 
 /* Index of first unused in `files'.  */
-static int files_index;  /* FIXME: rename this to e.g. cwd_n_used */
+static size_t files_index;  /* FIXME: rename this to e.g. cwd_n_used */
 
 /* When nonzero, in a color listing, color each symlink name according to the
    type of file it points to.  Otherwise, color them according to the `ln'
@@ -623,7 +623,7 @@ static struct quoting_options *dirname_q
 
 /* The number of chars per hardware tab stop.  Setting this to zero
    inhibits the use of TAB characters for separating columns.  -T */
-static int tabsize;
+static size_t tabsize;
 
 /* Nonzero means we are listing the working directory because no
    non-option arguments were given. */
@@ -637,7 +637,7 @@ static int print_dir_name;
 /* The line length to use for breaking lines in many-per-line format.
    Can be set with -w.  */
 
-static int line_length;
+static size_t line_length;
 
 /* If nonzero, the file listing format requires that stat be called on
    each file. */
@@ -790,16 +790,16 @@ static enum color_type const color_types
 /* Information about filling a column.  */
 struct column_info
 {
-  int valid_len;
-  int line_len;
-  int *col_arr;
+  bool valid_len;
+  size_t line_len;
+  size_t *col_arr;
 };
 
 /* Array with information about column filledness.  */
 static struct column_info *column_info;
 
 /* Maximum number of columns ever possible for this display.  */
-static int max_idx;
+static size_t max_idx;
 
 /* The minimum width of a colum is 3: 1 character for the name and 2
    for the separating white space.  */
@@ -895,18 +895,18 @@ dev_ino_pop (void)
 static void
 dired_dump_obstack (const char *prefix, struct obstack *os)
 {
-  int n_pos;
+  size_t n_pos;
 
   n_pos = obstack_object_size (os) / sizeof (dired_pos);
   if (n_pos > 0)
     {
-      int i;
+      size_t i;
       size_t *pos;
 
       pos = (size_t *) obstack_finish (os);
       fputs (prefix, stdout);
       for (i = 0; i < n_pos; i++)
-       printf (" %lu", (unsigned long) pos[i]);
+       printf (" %lu", (unsigned long int) pos[i]);
       putchar ('\n');
     }
 }
@@ -943,7 +943,7 @@ visit_dir (dev_t dev, ino_t ino)
   struct dev_ino *ent_from_table;
   int found_match;
 
-  ent = XMALLOC (struct dev_ino, 1);
+  ent = xmalloc (sizeof *ent);
   ent->st_ino = ino;
   ent->st_dev = dev;
 
@@ -1059,10 +1059,10 @@ main (int argc, char **argv)
        check_symlink_color = 1;
 
       {
-       unsigned j;
+       unsigned int j;
        static int const sigs[] = { SIGHUP, SIGINT, SIGPIPE,
                                    SIGQUIT, SIGTERM, SIGTSTP };
-       unsigned nsigs = sizeof sigs / sizeof *sigs;
+       unsigned int nsigs = sizeof sigs / sizeof *sigs;
 #ifdef SA_NOCLDSTOP
        struct sigaction oldact, newact;
        sigset_t caught_signals;
@@ -1126,7 +1126,7 @@ main (int argc, char **argv)
     }
 
   nfiles = 100;
-  files = XMALLOC (struct fileinfo, nfiles);
+  files = xnmalloc (nfiles, sizeof *files);
   files_index = 0;
 
   clear_files ();
@@ -1314,11 +1314,11 @@ decode_switches (int argc, char **argv)
     char const *p = getenv ("COLUMNS");
     if (p && *p)
       {
-       long int tmp_long;
-       if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
-           && 0 < tmp_long && tmp_long <= INT_MAX)
+       unsigned long int tmp_ulong;
+       if (xstrtoul (p, NULL, 0, &tmp_ulong, NULL) == LONGINT_OK
+           && 0 < tmp_ulong && tmp_ulong <= SIZE_MAX)
          {
-           line_length = (int) tmp_long;
+           line_length = tmp_ulong;
          }
        else
          {
@@ -1333,7 +1333,8 @@ decode_switches (int argc, char **argv)
   {
     struct winsize ws;
 
-    if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0)
+    if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1
+       && 0 < ws.ws_col && ws.ws_col <= SIZE_MAX)
       line_length = ws.ws_col;
   }
 #endif
@@ -1345,11 +1346,11 @@ decode_switches (int argc, char **argv)
     tabsize = 8;
     if (!getenv ("POSIXLY_CORRECT") && (p = getenv ("TABSIZE")))
       {
-       long int tmp_long;
-       if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
-           && 0 <= tmp_long && tmp_long <= INT_MAX)
+       unsigned long int tmp_ulong;
+       if (xstrtoul (p, NULL, 0, &tmp_ulong, NULL) == LONGINT_OK
+           && tmp_ulong <= SIZE_MAX)
          {
-           tabsize = (int) tmp_long;
+           tabsize = tmp_ulong;
          }
        else
          {
@@ -1468,12 +1469,12 @@ decode_switches (int argc, char **argv)
 
        case 'w':
          {
-           long int tmp_long;
-           if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
-               || tmp_long <= 0 || tmp_long > INT_MAX)
+           unsigned long int tmp_ulong;
+           if (xstrtoul (optarg, NULL, 0, &tmp_ulong, NULL) != LONGINT_OK
+               || ! (0 < tmp_ulong && tmp_ulong <= SIZE_MAX))
              error (EXIT_FAILURE, 0, _("invalid line width: %s"),
                     quotearg (optarg));
-           line_length = (int) tmp_long;
+           line_length = tmp_ulong;
            break;
          }
 
@@ -1542,12 +1543,12 @@ decode_switches (int argc, char **argv)
 
        case 'T':
          {
-           long int tmp_long;
-           if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
-               || tmp_long < 0 || tmp_long > INT_MAX)
+           unsigned long int tmp_ulong;
+           if (xstrtoul (optarg, NULL, 0, &tmp_ulong, NULL) != LONGINT_OK
+               || SIZE_MAX < tmp_ulong)
              error (EXIT_FAILURE, 0, _("invalid tab size: %s"),
                     quotearg (optarg));
-           tabsize = (int) tmp_long;
+           tabsize = tmp_ulong;
            break;
          }
 
@@ -1754,7 +1755,8 @@ decode_switches (int argc, char **argv)
 /* Parse a string as part of the LS_COLORS variable; this may involve
    decoding all kinds of escape characters.  If equals_end is set an
    unescaped equal sign ends the string, otherwise only a : or \0
-   does.  Returns the number of characters output, or -1 on failure.
+   does.  Set *OUTPUT_COUNT to the number of bytes output.  Return
+   true if successful.
 
    The resulting string is *not* null-terminated, but may contain
    embedded nulls.
@@ -1763,11 +1765,12 @@ decode_switches (int argc, char **argv)
    the first free byte after the array and the character that ended
    the input string, respectively.  */
 
-static int
-get_funky_string (char **dest, const char **src, int equals_end)
+static bool
+get_funky_string (char **dest, const char **src, bool equals_end,
+                 size_t *output_count)
 {
   int num;                     /* For numerical codes */
-  int count;                   /* Something to count with */
+  size_t count;                        /* Something to count with */
   enum {
     ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR
   } state;
@@ -1952,8 +1955,9 @@ get_funky_string (char **dest, const cha
 
   *dest = q;
   *src = p;
+  *output_count = count;
 
-  return state == ST_ERROR ? -1 : count;
+  return state != ST_ERROR;
 }
 
 static void
@@ -1996,15 +2000,15 @@ parse_ls_color (void)
                 override an earlier one, which can be useful for
                 having terminal-specific defs override global).  */
 
-             ext = XMALLOC (struct color_ext_type, 1);
+             ext = xmalloc (sizeof *ext);
              ext->next = color_ext_list;
              color_ext_list = ext;
 
              ++p;
              ext->ext.string = buf;
 
-             state = (ext->ext.len =
-                      get_funky_string (&buf, &p, 1)) < 0 ? -1 : 4;
+             state = (get_funky_string (&buf, &p, true, &ext->ext.len)
+                      ? 4 : -1);
              break;
 
            case '\0':
@@ -2037,8 +2041,9 @@ parse_ls_color (void)
                  if (STREQ (label, indicator_name[ind_no]))
                    {
                      color_indicator[ind_no].string = buf;
-                     state = ((color_indicator[ind_no].len =
-                               get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1);
+                     state = (get_funky_string (&buf, &p, false,
+                                                &color_indicator[ind_no].len)
+                              ? 1 : -1);
                      break;
                    }
                }
@@ -2051,8 +2056,8 @@ parse_ls_color (void)
          if (*(p++) == '=')
            {
              ext->seq.string = buf;
-             state = (ext->seq.len =
-                      get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1;
+             state = (get_funky_string (&buf, &p, false, &ext->seq.len)
+                      ? 1 : -1);
            }
          else
            state = -1;
@@ -2096,7 +2101,7 @@ queue_directory (const char *name, const
 {
   struct pending *new;
 
-  new = XMALLOC (struct pending, 1);
+  new = xmalloc (sizeof *new);
   new->realname = realname ? xstrdup (realname) : NULL;
   new->name = name ? xstrdup (name) : NULL;
   new->next = pending_dirs;
@@ -2251,7 +2256,7 @@ add_ignore_pattern (const char *pattern)
 {
   register struct ignore_pattern *ignore;
 
-  ignore = XMALLOC (struct ignore_pattern, 1);
+  ignore = xmalloc (sizeof *ignore);
   ignore->pattern = pattern;
   /* Add it to the head of the linked list. */
   ignore->next = ignore_patterns;
@@ -2286,7 +2291,7 @@ file_interesting (const struct dirent *n
 static void
 clear_files (void)
 {
-  register int i;
+  register size_t i;
 
   for (i = 0; i < files_index; i++)
     {
@@ -2312,8 +2317,8 @@ gobble_file (const char *name, enum file
 
   if (files_index == nfiles)
     {
+      files = xnrealloc (files, nfiles, 2 * sizeof *files);
       nfiles *= 2;
-      files = XREALLOC (files, struct fileinfo, nfiles);
     }
 
   files[files_index].linkname = 0;
@@ -2539,7 +2544,8 @@ basename_is_dot_or_dotdot (const char *n
 static void
 extract_dirs_from_files (const char *dirname, int ignore_dot_and_dot_dot)
 {
-  register int i, j;
+  register size_t i;
+  register size_t j;
 
   if (*dirname && LOOP_DETECT)
     {
@@ -2551,7 +2557,7 @@ extract_dirs_from_files (const char *dir
 
   /* Queue the directories last one first, because queueing reverses the
      order.  */
-  for (i = files_index - 1; i >= 0; i--)
+  for (i = files_index; i-- != 0; )
     if ((files[i].filetype == directory || files[i].filetype == arg_directory)
        && (!ignore_dot_and_dot_dot
            || !basename_is_dot_or_dotdot (files[i].name)))
@@ -2780,7 +2786,7 @@ sort_files (void)
 static void
 print_current_files (void)
 {
-  register int i;
+  register size_t i;
 
   switch (format)
     {
@@ -2901,7 +2907,7 @@ format_user (char *buffer, uid_t u)
   if (name)
     sprintf (buffer, "%-8s ", name);
   else
-    sprintf (buffer, "%-8lu ", (unsigned long) u);
+    sprintf (buffer, "%-8lu ", (unsigned long int) u);
   return strlen (buffer);
 }
 
@@ -2975,7 +2981,7 @@ print_long_format (const struct fileinfo
 
   /* The last byte of the mode string is the POSIX
      "optional alternate access method flag".  */
-  sprintf (p, "%s %3lu ", modebuf, (unsigned long) f->stat.st_nlink);
+  sprintf (p, "%s %3lu ", modebuf, (unsigned long int) f->stat.st_nlink);
   p += strlen (p);
 
   if (print_owner)
@@ -2987,7 +2993,7 @@ print_long_format (const struct fileinfo
       if (group_name)
        sprintf (p, "%-8s ", group_name);
       else
-       sprintf (p, "%-8lu ", (unsigned long) f->stat.st_gid);
+       sprintf (p, "%-8lu ", (unsigned long int) f->stat.st_gid);
       p += strlen (p);
     }
 
@@ -2996,8 +3002,8 @@ print_long_format (const struct fileinfo
 
   if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode))
     sprintf (p, "%3lu, %3lu ",
-            (unsigned long) major (f->stat.st_rdev),
-            (unsigned long) minor (f->stat.st_rdev));
+            (unsigned long int) major (f->stat.st_rdev),
+            (unsigned long int) minor (f->stat.st_rdev));
   else
     {
       char hbuf[LONGEST_HUMAN_READABLE + 1];
@@ -3399,7 +3405,7 @@ print_color_indicator (const char *name,
          name += len;          /* Pointer to final \0.  */
          for (ext = color_ext_list; ext != NULL; ext = ext->next)
            {
-             if ((size_t) ext->ext.len <= len
+             if (ext->ext.len <= len
                  && strncmp (name - ext->ext.len, ext->ext.string,
                              ext->ext.len) == 0)
                break;
@@ -3416,12 +3422,12 @@ print_color_indicator (const char *name,
 static void
 put_indicator (const struct bin_str *ind)
 {
-  register int i;
+  register size_t i;
   register const char *p;
 
   p = ind->string;
 
-  for (i = ind->len; i > 0; --i)
+  for (i = ind->len; i != 0; --i)
     putchar (*(p++));
 }
 
@@ -3432,17 +3438,17 @@ static int
 put_indicator_direct (const struct bin_str *ind)
 {
   size_t len;
-  if (ind->len <= 0)
+  if (ind->len == 0)
     return 0;
 
   len = ind->len;
   return (full_write (STDOUT_FILENO, ind->string, len) != len);
 }
 
-static int
+static size_t
 length_of_file_name_and_frills (const struct fileinfo *f)
 {
-  register int len = 0;
+  register size_t len = 0;
   size_t name_width;
 
   if (print_inode)
@@ -3480,14 +3486,14 @@ static void
 print_many_per_line (void)
 {
   struct column_info *line_fmt;
-  int filesno;                 /* Index into files. */
-  int row;                     /* Current row. */
-  int max_name_length;         /* Length of longest file name + frills. */
-  int name_length;             /* Length of each file name + frills. */
-  int pos;                     /* Current character column. */
-  int cols;                    /* Number of files across. */
-  int rows;                    /* Maximum number of files down. */
-  int max_cols;
+  size_t filesno;              /* Index into files. */
+  size_t row;                  /* Current row. */
+  size_t max_name_length;      /* Length of longest file name + frills. */
+  size_t name_length;          /* Length of each file name + frills. */
+  size_t pos;                  /* Current character column. */
+  size_t cols;                 /* Number of files across. */
+  size_t rows;                 /* Maximum number of files down. */
+  size_t max_cols;
 
   /* Normally the maximum number of columns is determined by the
      screen width.  But if few files are available this might limit it
@@ -3497,7 +3503,7 @@ print_many_per_line (void)
   /* Compute the maximum number of possible columns.  */
   for (filesno = 0; filesno < files_index; ++filesno)
     {
-      int i;
+      size_t i;
 
       name_length = length_of_file_name_and_frills (files + filesno);
 
@@ -3505,8 +3511,8 @@ print_many_per_line (void)
        {
          if (column_info[i].valid_len)
            {
-             int idx = filesno / ((files_index + i) / (i + 1));
-             int real_length = name_length + (idx == i ? 0 : 2);
+             size_t idx = filesno / ((files_index + i) / (i + 1));
+             size_t real_length = name_length + (idx == i ? 0 : 2);
 
              if (real_length > column_info[i].col_arr[idx])
                {
@@ -3534,7 +3540,7 @@ print_many_per_line (void)
 
   for (row = 0; row < rows; row++)
     {
-      int col = 0;
+      size_t col = 0;
       filesno = row;
       pos = 0;
       /* Print the next row.  */
@@ -3559,12 +3565,12 @@ static void
 print_horizontal (void)
 {
   struct column_info *line_fmt;
-  int filesno;
-  int max_name_length;
-  int name_length;
-  int cols;
-  int pos;
-  int max_cols;
+  size_t filesno;
+  size_t max_name_length;
+  size_t name_length;
+  size_t cols;
+  size_t pos;
+  size_t max_cols;
 
   /* Normally the maximum number of columns is determined by the
      screen width.  But if few files are available this might limit it
@@ -3575,7 +3581,7 @@ print_horizontal (void)
   max_name_length = 0;
   for (filesno = 0; filesno < files_index; ++filesno)
     {
-      int i;
+      size_t i;
 
       name_length = length_of_file_name_and_frills (files + filesno);
 
@@ -3583,8 +3589,8 @@ print_horizontal (void)
        {
          if (column_info[i].valid_len)
            {
-             int idx = filesno % (i + 1);
-             int real_length = name_length + (idx == i ? 0 : 2);
+             size_t idx = filesno % (i + 1);
+             size_t real_length = name_length + (idx == i ? 0 : 2);
 
              if (real_length > column_info[i].col_arr[idx])
                {
@@ -3616,7 +3622,7 @@ print_horizontal (void)
   /* Now the rest.  */
   for (filesno = 1; filesno < files_index; ++filesno)
     {
-      int col = filesno % cols;
+      size_t col = filesno % cols;
 
       if (col == 0)
        {
@@ -3640,8 +3646,9 @@ print_horizontal (void)
 static void
 print_with_commas (void)
 {
-  int filesno;
-  int pos, old_pos;
+  size_t filesno;
+  size_t pos;
+  size_t old_pos;
 
   pos = 0;
 
@@ -3673,11 +3680,11 @@ print_with_commas (void)
    Use a TAB character instead of two or more spaces whenever possible.  */
 
 static void
-indent (int from, int to)
+indent (size_t from, size_t to)
 {
   while (from < to)
     {
-      if (tabsize > 0 && to / tabsize > (from + 1) / tabsize)
+      if (tabsize != 0 && to / tabsize > (from + 1) / tabsize)
        {
          putchar ('\t');
          from += tabsize - from % tabsize;
@@ -3716,7 +3723,7 @@ attach (char *dest, const char *dirname,
 static void
 init_column_info (void)
 {
-  int i;
+  size_t i;
   int allocate = 0;
 
   max_idx = line_length / MIN_COLUMN_WIDTH;
@@ -3725,19 +3732,20 @@ init_column_info (void)
 
   if (column_info == NULL)
     {
-      column_info = XMALLOC (struct column_info, max_idx);
+      column_info = xnmalloc (max_idx, sizeof *column_info);
       allocate = 1;
     }
 
   for (i = 0; i < max_idx; ++i)
     {
-      int j;
+      size_t j;
 
-      column_info[i].valid_len = 1;
+      column_info[i].valid_len = true;
       column_info[i].line_len = (i + 1) * MIN_COLUMN_WIDTH;
 
       if (allocate)
-       column_info[i].col_arr = XMALLOC (int, i + 1);
+       column_info[i].col_arr = xnmalloc (i + 1,
+                                          sizeof column_info[i].col_arr[0]);
 
       for (j = 0; j <= i; ++j)
        column_info[i].col_arr[j] = MIN_COLUMN_WIDTH;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]