Fix 29149 - another UTF8 cache bug hit by substr.
SADAHIRO Tomoyuki [Thu, 29 Apr 2004 10:53:17 +0000 (19:53 +0900)]
Regression test from:

Subject: Re: [perl #29149] substr/UTF8 related problem with perl 5.8.3 on linux
Message-Id: <20040429103926.5BA6.BQW10602@nifty.com>
Date: Thu, 29 Apr 2004 10:53:17 +0900

p4raw-id: //depot/perl@22755

sv.c
t/op/substr.t

diff --git a/sv.c b/sv.c
index 076ee17..9972817 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -6437,8 +6437,7 @@ Perl_sv_pos_u2b(pTHX_ register SV *sv, I32* offsetp, I32* lenp)
                             s += UTF8SKIP(s);
                   if (s >= send)
                        s = send;
-                   if (utf8_mg_pos_init(sv, &mg, &cache, 2, lenp, s, start))
-                       cache[2] += *offsetp;
+                   utf8_mg_pos_init(sv, &mg, &cache, 2, lenp, s, start);
              }
              *lenp = s - start;
         }
@@ -6531,6 +6530,11 @@ Perl_sv_pos_b2u(pTHX_ register SV* sv, I32* offsetp)
 
                        cache[0] -= ubackw;
                        *offsetp = cache[0];
+
+                       /* Drop the stale "length" cache */
+                       cache[2] = 0;
+                       cache[3] = 0;
+
                        return;
                    }
                }
@@ -6568,6 +6572,9 @@ Perl_sv_pos_b2u(pTHX_ register SV* sv, I32* offsetp)
 
            cache[0] = len;
            cache[1] = *offsetp;
+           /* Drop the stale "length" cache */
+           cache[2] = 0;
+           cache[3] = 0;
        }
 
        *offsetp = len;
index 681ac6d..08f4165 100755 (executable)
@@ -1,6 +1,6 @@
 #!./perl
 
-print "1..188\n";
+print "1..189\n";
 
 #P = start of string  Q = start of substr  R = end of substr  S = end of string
 
@@ -640,3 +640,14 @@ ok 174, $x eq "\x{100}\x{200}\xFFb";
     $foo = '123456789';
     ok 188, bar eq '123456789';
 }
+
+# [perl #29149]
+{
+    my $text  = "0123456789\xED ";
+    utf8::upgrade($text);
+    my $pos = 5;
+    pos($text) = $pos;
+    my $a = substr($text, $pos, $pos);
+    ok 189, substr($text,$pos,1) eq $pos;
+
+}