re PR preprocessor/77699 (suspicious code in get_next_line)
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Mon, 3 Oct 2016 14:05:46 +0000 (14:05 +0000)
committerBernd Edlinger <edlinger@gcc.gnu.org>
Mon, 3 Oct 2016 14:05:46 +0000 (14:05 +0000)
2016-10-03  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        PR preprocessor/77699
        * input.c (maybe_grow): Don't allocate one byte extra headroom.
        (get_next_line): Return false on error.
        (read_next_line): Removed, use get_next_line instead.
        (read_line_num): Don't copy the line.
        (location_get_source_line): Don't use static data.
        (selftest::test_reading_source_line): Add more test cases.

From-SVN: r240713

gcc/ChangeLog
gcc/input.c

index 2b771d1bd0dcd66a34ef621aa904e5630cb1c26f..824d1a8602c83af4ecb572d2b167a30862e3ae47 100644 (file)
@@ -1,3 +1,13 @@
+2016-10-03  Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       PR preprocessor/77699
+       * input.c (maybe_grow): Don't allocate one byte extra headroom.
+       (get_next_line): Return false on error.
+       (read_next_line): Removed, use get_next_line instead.
+       (read_line_num): Don't copy the line.
+       (location_get_source_line): Don't use static data.
+       (selftest::test_reading_source_line): Add more test cases.
+
 2016-10-03  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        Revert
index 9b263781776242af309a4bc4c1764c11fc8714b8..67f727e5a2b7292b83a37cf957cc3f106c144238 100644 (file)
@@ -432,7 +432,7 @@ maybe_grow (fcache *c)
     return;
 
   size_t size = c->size == 0 ? fcache_buffer_size : c->size * 2;
-  c->data = XRESIZEVEC (char, c->data, size + 1);
+  c->data = XRESIZEVEC (char, c->data, size);
   c->size = size;
 }
 
@@ -472,14 +472,13 @@ maybe_read_data (fcache *c)
 
 /* Read a new line from file FP, using C as a cache for the data
    coming from the file.  Upon successful completion, *LINE is set to
-   the beginning of the line found.  Space for that line has been
-   allocated in the cache thus *LINE has the same life time as C.
+   the beginning of the line found.  *LINE points directly in the
+   line cache and is only valid until the next call of get_next_line.
    *LINE_LEN is set to the length of the line.  Note that the line
    does not contain any terminal delimiter.  This function returns
    true if some data was read or process from the cache, false
-   otherwise.  Note that subsequent calls to get_next_line return the
-   next lines of the file and might overwrite the content of
-   *LINE.  */
+   otherwise.  Note that subsequent calls to get_next_line might
+   make the content of *LINE invalid.  */
 
 static bool
 get_next_line (fcache *c, char **line, ssize_t *line_len)
@@ -534,7 +533,7 @@ get_next_line (fcache *c, char **line, ssize_t *line_len)
     }
 
   if (ferror (c->fp))
-    return -1;
+    return false;
 
   /* At this point, we've found the end of the of line.  It either
      points to the '\n' or to one byte after the last byte of the
@@ -597,36 +596,6 @@ get_next_line (fcache *c, char **line, ssize_t *line_len)
   return true;
 }
 
-/* Reads the next line from FILE into *LINE.  If *LINE is too small
-   (or NULL) it is allocated (or extended) to have enough space to
-   containe the line.  *LINE_LENGTH must contain the size of the
-   initial*LINE buffer.  It's then updated by this function to the
-   actual length of the returned line.  Note that the returned line
-   can contain several zero bytes.  Also note that the returned string
-   is allocated in static storage that is going to be re-used by
-   subsequent invocations of read_line.  */
-
-static bool
-read_next_line (fcache *cache, char ** line, ssize_t *line_len)
-{
-  char *l = NULL;
-  ssize_t len = 0;
-
-  if (!get_next_line (cache, &l, &len))
-    return false;
-
-  if (*line == NULL)
-    *line = XNEWVEC (char, len);
-  else
-    if (*line_len < len)
-       *line = XRESIZEVEC (char, *line, len);
-
-  memcpy (*line, l, len);
-  *line_len = len;
-
-  return true;
-}
-
 /* Consume the next bytes coming from the cache (or from its
    underlying file if there are remaining unread bytes in the file)
    until we reach the next end-of-line (or end-of-file).  There is no
@@ -643,15 +612,15 @@ goto_next_line (fcache *cache)
 }
 
 /* Read an arbitrary line number LINE_NUM from the file cached in C.
-   The line is copied into *LINE.  *LINE_LEN must have been set to the
-   length of *LINE.  If *LINE is too small (or NULL) it's extended (or
-   allocated) and *LINE_LEN is adjusted accordingly.  *LINE ends up
-   with a terminal zero byte and can contain additional zero bytes.
+   If the line was read successfully, *LINE points to the beginning
+   of the line in the file cache and *LINE_LEN is the length of the
+   line.  *LINE is not nul-terminated, but may contain zero bytes.
+   *LINE is only valid until the next call of read_line_num.
    This function returns bool if a line was read.  */
 
 static bool
 read_line_num (fcache *c, size_t line_num,
-              char ** line, ssize_t *line_len)
+              char **line, ssize_t *line_len)
 {
   gcc_assert (line_num > 0);
 
@@ -703,14 +672,9 @@ read_line_num (fcache *c, size_t line_num,
 
          if (i && i->line_num == line_num)
            {
-             /* We have the start/end of the line.  Let's just copy
-                it again and we are done.  */
-             ssize_t len = i->end_pos - i->start_pos + 1;
-             if (*line_len < len)
-               *line = XRESIZEVEC (char, *line, len);
-             memmove (*line, c->data + i->start_pos, len);
-             (*line)[len - 1] = '\0';
-             *line_len = --len;
+             /* We have the start/end of the line.  */
+             *line = c->data + i->start_pos;
+             *line_len = i->end_pos - i->start_pos;
              return true;
            }
 
@@ -735,21 +699,22 @@ read_line_num (fcache *c, size_t line_num,
 
   /* The line we want is the next one.  Let's read and copy it back to
      the caller.  */
-  return read_next_line (c, line, line_len);
+  return get_next_line (c, line, line_len);
 }
 
-/* Return the physical source line that corresponds to FILE_PATH/LINE in a
-   buffer that is statically allocated.  The newline is replaced by
-   the null character.  Note that the line can contain several null
-   characters, so LINE_LEN, if non-null, points to the actual length
-   of the line.  */
+/* Return the physical source line that corresponds to FILE_PATH/LINE.
+   The line is not nul-terminated.  The returned pointer is only
+   valid until the next call of location_get_source_line.
+   Note that the line can contain several null characters,
+   so LINE_LEN, if non-null, points to the actual length of the line.
+   If the function fails, NULL is returned.  */
 
 const char *
 location_get_source_line (const char *file_path, int line,
                          int *line_len)
 {
-  static char *buffer;
-  static ssize_t len;
+  char *buffer;
+  ssize_t len;
 
   if (line == 0)
     return NULL;
@@ -1818,22 +1783,27 @@ test_reading_source_line ()
   temp_source_file tmp (SELFTEST_LOCATION, ".txt",
                        "01234567890123456789\n"
                        "This is the test text\n"
-                       "This is the 3rd line\n");
+                       "This is the 3rd line");
 
   /* Read back a specific line from the tempfile.  */
   int line_size;
   const char *source_line = location_get_source_line (tmp.get_filename (),
-                                                     2, &line_size);
+                                                     3, &line_size);
+  ASSERT_TRUE (source_line != NULL);
+  ASSERT_EQ (20, line_size);
+  ASSERT_TRUE (!strncmp ("This is the 3rd line",
+                        source_line, line_size));
+
+  source_line = location_get_source_line (tmp.get_filename (),
+                                         2, &line_size);
   ASSERT_TRUE (source_line != NULL);
   ASSERT_EQ (21, line_size);
-  if (!strncmp ("This is the test text",
-               source_line, line_size))
-    ::selftest::pass (SELFTEST_LOCATION,
-                     "source_line matched expected value");
-  else
-    ::selftest::fail (SELFTEST_LOCATION,
-                     "source_line did not match expected value");
+  ASSERT_TRUE (!strncmp ("This is the test text",
+                        source_line, line_size));
 
+  source_line = location_get_source_line (tmp.get_filename (),
+                                         4, &line_size);
+  ASSERT_TRUE (source_line == NULL);
 }
 
 /* Tests of lexing.  */