[PATCH] fixup: reference to uninitialized variable with invalid sequence

Norihiro Tanaka <[email protected]> Thu, 06 Nov 2014 00:36:54 +0900
Newsgroups gmane.comp.gnu.utils.bugs
Message-ID <[email protected]>
Uninitialized variable are referred with invalid sequence in
str_append_modified().

When mbrtowc() returns (size_t) -1, wc is not changed, even if wc is
uninitialized.  below may return unexpected result in order that the
value is referred at a following position in source code.

  $ echo a | LC_ALL=ja_JP.eucJP ./sed/sed -e 's/a/b\U\xb2c/'
0001-fixup-reference-to-uninitialized-variable-with-inval.patch (text/plain, 1.9 KB)
From 8132bf14835e0652bb86bddb634aa5af0b274d90 Mon Sep 17 00:00:00 2001
From: Norihiro Tanaka <[email protected]>
Date: Wed, 5 Nov 2014 23:59:03 +0900
Subject: [PATCH] fixup: reference to uninitialized variable with invalid
 sequence

* sed/execute.c (str_append_modified): Fix reference to uninitialized
variable with invalid sequence.
---
 sed/execute.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/sed/execute.c b/sed/execute.c
index 2e13ee2..95640ab 100644
--- a/sed/execute.c
+++ b/sed/execute.c
@@ -220,13 +220,23 @@ str_append_modified(struct line *to, const char *string, size_t length,
   while (length)
     {
       wchar_t wc;
-      int n = MBRTOWC (&wc, string, length, &from_stat);
+      size_t n = MBRTOWC (&wc, string, length, &from_stat);
 
       /* An invalid sequence is treated like a singlebyte character. */
       if (n == -1)
         {
           memset (&to->mbstate, 0, sizeof (from_stat));
+
+          type &= ~(REPL_LOWERCASE_FIRST | REPL_UPPERCASE_FIRST);
+          if (type == REPL_ASIS)
+            {
+              str_append(to, string, length);
+              return;
+            }
+
           n = 1;
+          string += n, length -= n;
+          continue;
         }
 
       if (n > 0)
@@ -249,13 +259,18 @@ str_append_modified(struct line *to, const char *string, size_t length,
           type &= ~(REPL_LOWERCASE_FIRST | REPL_UPPERCASE_FIRST);
 	  if (type == REPL_ASIS)
 	    {
+              /* Copy the new wide character to the end of the string. */
 	      n = WCRTOMB (to->active + to->length, wc, &to->mbstate);
 	      to->length += n;
+	      if (n == -1 || n == -2)
+		{
+		  fprintf (stderr, "Case conversion produced an invalid character!");
+		  abort ();
+		}
 	      str_append(to, string, length);
 	      return;
 	    }
         }
-
       else if (type & REPL_UPPERCASE)
         wc = towupper(wc);
       else
-- 
2.1.3