bug-bash
[Top][All Lists]
Advanced

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

[patch] UTF-8: ${var%...}-style parameter expansion broken


From: Tim Waugh
Subject: [patch] UTF-8: ${var%...}-style parameter expansion broken
Date: Mon, 5 Jan 2004 11:00:32 +0000
User-agent: Mutt/1.4.1i

> Repeat-By:
>       See:
>       https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=112657

Here is a patch that works for me.

Tim.
*/

--- bash-2.05b/subst.c.subst    2004-01-05 10:41:32.575765192 +0000
+++ bash-2.05b/subst.c  2004-01-05 10:44:18.680813090 +0000
@@ -2813,6 +2813,8 @@
   register int len;
   register char *end;
   register char *p, *ret, c;
+  unsigned char *mblen;
+  DECLARE_MBSTATE;
 
   if (param == NULL || *param == '\0')
     return (param);
@@ -2822,10 +2824,35 @@
   len = STRLEN (param);
   end = param + len;
 
+  /* Pre-calculate character boundaries. */
+  if (MB_CUR_MAX > 1)
+    switch (op)
+      {
+       int i, offset;
+       char *p;
+       unsigned char last;
+
+      case RP_LONG_LEFT:
+      case RP_SHORT_RIGHT:
+       i = offset = 0;
+       last = 0;
+       mblen = xmalloc (len);
+       memset (mblen, 0, len);
+       while (param[last])
+         {
+           ADVANCE_CHAR (param, len, offset);
+           mblen[last] = offset - last;
+           last = offset;
+         }
+      }
+
   switch (op)
     {
+      int offset;
+
       case RP_LONG_LEFT:       /* remove longest match at start */
-       for (p = end; p >= param; p--)
+       p = end;
+       while (p >= param)
          {
            c = *p; *p = '\0';
            if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
@@ -2834,11 +2861,21 @@
                return (savestring (p));
              }
            *p = c;
+
+           if (MB_CUR_MAX > 1)
+             {
+               while (p >= param)
+                 if (mblen[--p - param])
+                   break;
+             }
+           else p--;
          }
        break;
 
       case RP_SHORT_LEFT:      /* remove shortest match at start */
-       for (p = param; p <= end; p++)
+       p = param;
+       offset = 0;
+       while (p <= end)
          {
            c = *p; *p = '\0';
            if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
@@ -2847,11 +2884,20 @@
                return (savestring (p));
              }
            *p = c;
+           if (MB_CUR_MAX > 1)
+             {
+               ADVANCE_CHAR (param, len, offset);
+               p = param + offset;
+             }
+           else
+             p++;
          }
        break;
 
       case RP_LONG_RIGHT:      /* remove longest match at end */
-       for (p = param; p <= end; p++)
+       p = param;
+       offset = 0;
+       while (p <= end)
          {
            if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
              {
@@ -2860,11 +2906,20 @@
                *p = c;
                return (ret);
              }
+
+           if (MB_CUR_MAX > 1)
+             {
+               ADVANCE_CHAR (param, len, offset);
+               p = param + offset;
+             }
+           else
+             p++;
          }
        break;
 
       case RP_SHORT_RIGHT:     /* remove shortest match at end */
-       for (p = end; p >= param; p--)
+       p = end;
+       while (p >= param)
          {
            if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
              {
@@ -2873,6 +2928,15 @@
                *p = c;
                return (ret);
              }
+
+           if (MB_CUR_MAX > 1)
+             {
+               while (p >= param)
+                 if (mblen[--p - param])
+                   break;
+             }
+           else
+             p--;
          }
        break;
     }
@@ -4492,7 +4556,22 @@
     {
     case VT_VARIABLE:
     case VT_ARRAYMEMBER:
-      tt = substring (val, e1, e2);
+      if (MB_CUR_MAX > 1)
+       {
+         int start = 0, stop, i, slen = strlen (val);
+         DECLARE_MBSTATE;
+         i = e1;
+         while (val[start] && i--)
+           ADVANCE_CHAR (val, slen, start);
+         stop = start;
+         i = e2 - e1;
+         while (val[stop] && i--)
+           ADVANCE_CHAR (val, slen, stop);
+         tt = substring (val, start, stop);
+       }
+      else
+       tt = substring (val, e1, e2);
+
       if (vtype == VT_VARIABLE)
        FREE (val);
       if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))




reply via email to

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