Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Infinite loop in dopadding() with doublewidth chars, probably since (mm)



Trying to pad a string to a width with a double-width character that
can't be done results in an infinite loop, where old versions just
left it one character too narrow. For example:
echo ${(ml:10::ã:):-hello}

dopadding() seems to consist mostly of special cases, but i ended up
around line 990,

 986 if ((m = f % lpremul)) {
here f is 5 "hello", lpremul is 2 "ã", so m is 1
 987     /*
 988      * Some fraction of the repeated string needed.
 989      */
 990     /* Need this much... */
 991     c = m;
 992     /* ...skipping this much first. */
 993     m = lpremul - m;
m is still 1 here
 994     MB_METACHARINIT();
 995     for (t = premul; m > 0; ) {
 996         t += MB_METACHARLENCONV(t, &cchar);
this advances t 3 bytes, pointing directly at the null after the ã
 997         m -= WCPADWIDTH(cchar, multi_width);
this subtracts 2 from m, leaving -1
 998     }
 999     /* Now the rest of the repeated string. */
1000     while (c > 0) {
c is still 1 here
1001         cl = MB_METACHARLENCONV(t, &cchar);
this is 0, remember t is ""
1002         while (cl--)
1003             *r++ = *t++;
1004         c -= WCPADWIDTH(cchar, multi_width);
which means c is decremented by 0 here
1005     }
1006 }

I didn't get much further than this. I didn't even dare look in how
many places some similar code exists in the function. :)

-- 
Mikael Magnusson



Messages sorted by: Reverse Date, Date, Thread, Author