OSDN Git Service

* c-common.c (format_wanted_type): Add reading_from_flag.
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 7 Dec 2000 07:40:45 +0000 (07:40 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 7 Dec 2000 07:40:45 +0000 (07:40 +0000)
(print_char_table): Mark %s and %S formats with flag "R".
(check_format_info_main): Set up reading_from_flag appropriately.
If aflag, always set writing_in_flag rather than relying on the
format used being a scanf format and so having it set.
(check_format_types): Check for formats reading through null
pointers.

testsuite:
* gcc.dg/c90-printf-1.c: Add test for printf formats reading
through a null pointer.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@38104 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-common.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/c90-printf-1.c

index 8be376e..2119c93 100644 (file)
@@ -1,5 +1,15 @@
 2000-12-07  Joseph S. Myers  <jsm28@cam.ac.uk>
 
+       * c-common.c (format_wanted_type): Add reading_from_flag.
+       (print_char_table): Mark %s and %S formats with flag "R".
+       (check_format_info_main): Set up reading_from_flag appropriately.
+       If aflag, always set writing_in_flag rather than relying on the
+       format used being a scanf format and so having it set.
+       (check_format_types): Check for formats reading through null
+       pointers.
+
+2000-12-07  Joseph S. Myers  <jsm28@cam.ac.uk>
+
        * invoke.texi (-Wformat): Document what format features are
        checked.
 
index b42f320..7359b04 100644 (file)
@@ -1416,6 +1416,7 @@ typedef struct
      years in some locales, "4" for "2" which becomes "3" with an "E" modifier,
      "o" if use of strftime "O" is a GNU extension beyond C99,
      "W" if the argument is a pointer which is dereferenced and written into,
+     "R" if the argument is a pointer which is dereferenced and read from,
      "i" for printf integer formats where the '0' flag is ignored with
      precision, and "[" for the starting character of a scanf scanset.  */
   const char *flags2;
@@ -1521,6 +1522,9 @@ typedef struct format_wanted_type
   /* Whether the argument, dereferenced once, is written into and so the
      argument must not be a pointer to a const-qualified type.  */
   int writing_in_flag;
+  /* Whether the argument, dereferenced once, is read from and so
+     must not be a NULL pointer.  */
+  int reading_from_flag;
   /* If warnings should be of the form "field precision is not type int",
      the name to use (in this case "field precision"), otherwise NULL,
      for "%s format, %s arg" type messages.  If (in an extension), this
@@ -1694,23 +1698,23 @@ static const format_flag_pair strftime_flag_pairs[] =
 static const format_char_info print_char_table[] =
 {
   /* C89 conversion specifiers.  */
-  { "di",  0, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T99_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM  }, "-wp0 +'I", "i" },
-  { "oxX", 0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T99_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "-wp0#",    "i" },
-  { "u",   0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T99_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "-wp0'I",   "i" },
-  { "fgG", 0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#'", ""  },
-  { "eE",  0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#",  ""  },
-  { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T94_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",       ""  },
-  { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",      "c" },
-  { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",       "c" },
-  { "n",   1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T99_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM  }, "",         "W" },
+  { "di",  0, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T99_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM  }, "-wp0 +'I", "i"  },
+  { "oxX", 0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T99_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "-wp0#",    "i"  },
+  { "u",   0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T99_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "-wp0'I",   "i"  },
+  { "fgG", 0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#'", ""   },
+  { "eE",  0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#",  ""   },
+  { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T94_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",       ""   },
+  { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",      "cR" },
+  { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",       "c"  },
+  { "n",   1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T99_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM  }, "",         "W"  },
   /* C99 conversion specifiers.  */
-  { "F",   0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#'", ""  },
-  { "aA",  0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#",  ""  },
+  { "F",   0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#'", ""   },
+  { "aA",  0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#",  ""   },
   /* X/Open conversion specifiers.  */
-  { "C",   0, STD_EXT, { TEX_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",       ""  },
-  { "S",   1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",      ""  },
+  { "C",   0, STD_EXT, { TEX_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",       ""   },
+  { "S",   1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",      "R"  },
   /* GNU conversion specifiers.  */
-  { "m",   0, STD_EXT, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",      ""  },
+  { "m",   0, STD_EXT, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",      ""   },
   { NULL,  0, 0, NOLENGTHS, NULL, NULL }
 };
 
@@ -2718,6 +2722,7 @@ check_format_info_main (status, res, info, format_chars, format_length,
                  width_wanted_type.pointer_count = 0;
                  width_wanted_type.char_lenient_flag = 0;
                  width_wanted_type.writing_in_flag = 0;
+                 width_wanted_type.reading_from_flag = 0;
                  width_wanted_type.name = _("field width");
                  width_wanted_type.param = cur_param;
                  width_wanted_type.arg_num = arg_num;
@@ -2803,6 +2808,7 @@ check_format_info_main (status, res, info, format_chars, format_length,
                  precision_wanted_type.pointer_count = 0;
                  precision_wanted_type.char_lenient_flag = 0;
                  precision_wanted_type.writing_in_flag = 0;
+                 precision_wanted_type.reading_from_flag = 0;
                  precision_wanted_type.name = _("field precision");
                  precision_wanted_type.param = cur_param;
                  precision_wanted_type.arg_num = arg_num;
@@ -3129,8 +3135,16 @@ check_format_info_main (status, res, info, format_chars, format_length,
          if (strchr (fci->flags2, 'c') != 0)
            main_wanted_type.char_lenient_flag = 1;
          main_wanted_type.writing_in_flag = 0;
-         if (strchr (fci->flags2, 'W') != 0)
+         main_wanted_type.reading_from_flag = 0;
+         if (aflag)
            main_wanted_type.writing_in_flag = 1;
+         else
+           {
+             if (strchr (fci->flags2, 'W') != 0)
+               main_wanted_type.writing_in_flag = 1;
+             if (strchr (fci->flags2, 'R') != 0)
+               main_wanted_type.reading_from_flag = 1;
+           }
          main_wanted_type.name = NULL;
          main_wanted_type.param = cur_param;
          main_wanted_type.arg_num = arg_num;
@@ -3208,6 +3222,15 @@ check_format_types (status, types)
                                "writing through null pointer (arg %d)",
                                arg_num);
 
+             /* Check for reading through a NULL pointer.  */
+             if (types->reading_from_flag
+                 && i == 0
+                 && cur_param != 0
+                 && integer_zerop (cur_param))
+               status_warning (status,
+                               "reading through null pointer (arg %d)",
+                               arg_num);
+
              if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR)
                cur_param = TREE_OPERAND (cur_param, 0);
              else
index 340a765..444f2d6 100644 (file)
@@ -1,3 +1,8 @@
+2000-12-07  Joseph S. Myers  <jsm28@cam.ac.uk>
+
+       * gcc.dg/c90-printf-1.c: Add test for printf formats reading
+       through a null pointer.
+
 2000-12-06  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
 
        * g++.old-deja/g++.oliva/partspec1.C: Remove XFAIL.
index 85193ec..5058066 100644 (file)
@@ -245,4 +245,5 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
   printf ("%n", cn); /* { dg-warning "constant" "%n with const" } */
   printf ((const char *)L"foo"); /* { dg-warning "wide" "wide string" } */
   printf ("%n", (int *)0); /* { dg-warning "null" "%n with NULL" } */
+  printf ("%s", (char *)0); /* { dg-warning "null" "%s with NULL" } */
 }