diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 3b729b838b8cf0bddf6bab284c27670761ff2863..fc78ca810607e5b8a69b969e8e7df4dc7c8e2218 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,14 @@
+2012-12-03  Jakub Jelinek  <jakub@redhat.com>
+
+	PR bootstrap/55380
+	PR other/54691
+	* files.c (read_file_guts): Allocate extra 16 bytes instead of
+	1 byte at the end of buf.  Pass size + 16 instead of size
+	to _cpp_convert_input.
+	* charset.c (_cpp_convert_input): Reallocate if there aren't
+	at least 16 bytes beyond to.len in the buffer.  Clear 16 bytes
+	at to.text + to.len.
+
 2012-11-21  Steve Ellcey  <sellcey@mips.com>
 
 	PR pch/55399
diff --git a/libcpp/charset.c b/libcpp/charset.c
index cba19a67178c796dcef1c8c70ac5c43dcbc69071..09e2b7b45a243b82601ed17667c5f8153c745a01 100644
--- a/libcpp/charset.c
+++ b/libcpp/charset.c
@@ -1,6 +1,6 @@
 /* CPP Library - charsets
    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2008, 2009,
-   2010 Free Software Foundation, Inc.
+   2010, 2012 Free Software Foundation, Inc.
 
    Broken out of c-lex.c Apr 2003, adding valid C99 UCN ranges.
 
@@ -1729,9 +1729,15 @@ _cpp_convert_input (cpp_reader *pfile, const char *input_charset,
     iconv_close (input_cset.cd);
 
   /* Resize buffer if we allocated substantially too much, or if we
-     haven't enough space for the \n-terminator.  */
-  if (to.len + 4096 < to.asize || to.len >= to.asize)
-    to.text = XRESIZEVEC (uchar, to.text, to.len + 1);
+     haven't enough space for the \n-terminator or following
+     15 bytes of padding (used to quiet warnings from valgrind or
+     Address Sanitizer, when the optimized lexer accesses aligned
+     16-byte memory chunks, including the bytes after the malloced,
+     area, and stops lexing on '\n').  */
+  if (to.len + 4096 < to.asize || to.len + 16 > to.asize)
+    to.text = XRESIZEVEC (uchar, to.text, to.len + 16);
+
+  memset (to.text + to.len, '\0', 16);
 
   /* If the file is using old-school Mac line endings (\r only),
      terminate with another \r, not an \n, so that we do not mistake
diff --git a/libcpp/files.c b/libcpp/files.c
index 9f84d8c6e02ef9401ffd83e5e9cff1e3d91dd240..3aeb6f37881dd485fd3950e22c0026d603ca5d5c 100644
--- a/libcpp/files.c
+++ b/libcpp/files.c
@@ -671,7 +671,11 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
        the majority of C source files.  */
     size = 8 * 1024;
 
-  buf = XNEWVEC (uchar, size + 1);
+  /* The + 16 here is space for the final '\n' and 15 bytes of padding,
+     used to quiet warnings from valgrind or Address Sanitizer, when the
+     optimized lexer accesses aligned 16-byte memory chunks, including
+     the bytes after the malloced, area, and stops lexing on '\n'.  */
+  buf = XNEWVEC (uchar, size + 16);
   total = 0;
   while ((count = read (file->fd, buf + total, size - total)) > 0)
     {
@@ -682,7 +686,7 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
 	  if (regular)
 	    break;
 	  size *= 2;
-	  buf = XRESIZEVEC (uchar, buf, size + 1);
+	  buf = XRESIZEVEC (uchar, buf, size + 16);
 	}
     }
 
@@ -699,7 +703,7 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
 
   file->buffer = _cpp_convert_input (pfile,
 				     CPP_OPTION (pfile, input_charset),
-				     buf, size, total,
+				     buf, size + 16, total,
 				     &file->buffer_start,
 				     &file->st.st_size);
   file->buffer_valid = true;