nmh-workers
[Top] [All Lists]

[Nmh-workers] sbr/fmt_scan.c: cpstripped(): assert(w >= 0) Failure.

2017-04-24 10:02:47
Hi,

80a9e99f7078199500d2d53c8d77d1b92af06fbc added an assert(3) as part of
the -width-overflow fix for Valdis's email.

Bad news: Yesterday, I got two aborts in a row when running `scan +foo'
from git.  I then viewed the source, and after that it wouldn't happen.
:-(  Good news: A code dump was squirrelled away.

Bad news: By the time I thought of that, the executable I'd run had
changed.  Good news: gdb(1) is still happy to disassemble where I know
the execution was rather than where it thinks it was in the source, and
dump memory, so I've poked about it a bit.  Here's what I found in the
hope it helps fix it, and as a prompt to me should I get it to re-occur.

    if (!str)
        return;

0x00409774 <+0>:     push   %rbp
0x00409775 <+1>:     mov    %rsp,%rbp
0x00409778 <+4>:     sub    $0x40,%rsp
0x0040977c <+8>:     mov    %rdi,-0x28(%rbp)         dest
0x00409780 <+12>:    mov    %rsi,-0x30(%rbp)         max
0x00409784 <+16>:    mov    %rdx,-0x38(%rbp)         str
0x00409788 <+20>:    movl   $0x1,-0x4(%rbp)          prevCtrl
0x0040978f <+27>:    movq   $0x0,-0x18(%rbp)         altstr
0x00409797 <+35>:    cmpq   $0x0,-0x38(%rbp)         str
0x0040979c <+40>:    je     0x409931 <cpstripped+445>

    len = strlen(str);

0x004097a2 <+46>:    mov    -0x38(%rbp),%rax
0x004097a6 <+50>:    mov    %rax,%rdi                str
0x004097a9 <+53>:    callq  0x4025c0 <strlen@plt>
0x004097ae <+58>:    mov    %eax,-0x8(%rbp)          len

    if (mbtowc(NULL, NULL, 0)) {}  /* Reset shift state */

0x004097b1 <+61>:    mov    $0x0,%edx
0x004097b6 <+66>:    mov    $0x0,%esi
0x004097bb <+71>:    mov    $0x0,%edi
0x004097c0 <+76>:    callq  0x402830 <mbtowc@plt>

    while (*str != '\0' && len > 0 && max > 0) {

Skipped.

        char_len = mbtowc(&wide_char, str, len);

0x004097ca <+86>:    mov    -0x8(%rbp),%eax          len
0x004097cd <+89>:    movslq %eax,%rdx                len
0x004097d0 <+92>:    mov    -0x38(%rbp),%rcx         str
0x004097d4 <+96>:    lea    -0x20(%rbp),%rax         wide_char
0x004097d8 <+100>:   mov    %rcx,%rsi                str
0x004097db <+103>:   mov    %rax,%rdi                &wide_char
0x004097de <+106>:   callq  0x402830 <mbtowc@plt>
0x004097e3 <+111>:   mov    %eax,-0xc(%rbp)          char_len

        w = wcwidth(wide_char);

0x004097e6 <+114>:   mov    -0x20(%rbp),%eax         wide_char
0x004097e9 <+117>:   mov    %eax,%edi
0x004097eb <+119>:   callq  0x4028b0 <wcwidth@plt>
0x004097f0 <+124>:   mov    %eax,-0x1c(%rbp)         w

        assert(w >= 0);    /* This aborts. */

0x00409880 <+268>:  cmpl   $0x0,-0x1c(%rbp)
0x00409884 <+272>:  jns    0x40989f <cpstripped+299>
0x00409886 <+274>:  mov    $0x41f418,%ecx
0x0040988b <+279>:  mov    $0x12c,%edx
0x00409890 <+284>:  mov    $0x41effa,%esi
0x00409895 <+289>:  mov    $0x41f009,%edi
0x0040989a <+294>:  callq  0x402690 <__assert_fail@plt>

(gdb) x $rbp - 0x1c
0x7ffc861af084: 0xffffffff      w
(gdb) x $rbp - 0x20
0x7ffc861af080: 0x0000003f      wide_char = '?'
(gdb) x $rbp - 0xc
0x7ffc861af094: 0x00000001      char_len on '?'
(gdb) x $rbp - 0x38
0x7ffc861af068: 0x0327d1d3      str
(gdb) x $rbp - 0x8
0x7ffc861af098: 172             len, after len -= char_len

(gdb) x/32ub 0x0327d1c0
0x327d1c0:      46      56      32      77      66      41      32      97
0x327d1c8:      110     100     32      50      50      53      44      48
0x327d1d0:      48      48      10    [ 194 ]   161     195     145     32
0x327d1d8:      50      50      53      44      48      48      48      32

    $ printf '%02X' 46 56 32 77 66 41 32 97 110 100 32 50 50 53 44 48 48 48 10 \
    >     194 161 195 145 32 50 50 53 44 48 48 48 32; echo
    2E38204D422920616E64203232352C3030300AC2A1C391203232352C30303020
    $
    $ dc 
<<<'16i2E38204D422920616E64203232352C3030300AC2A1C391203232352C30303020P'; echo
    .8 MB) and 225,000
    ¡Ñ 225,000 
    $ 

The email in +foo with that fragment is text/plain, UTF-8, 8bit, with
this paragraph as the body preceded by two blank lines.

    Biggest image in the smallest space, "Here is a bzip2 file of 420 bytes
    that uncompresses to a PNG image of 6,132,534 bytes (5.8 MB) and 225,000
    ¡Ñ 225,000 pixels (50.625 gigapixels), which, if represented as a pixel
    buffer of 3 bytes per pixel, takes about 141.4 GB."
    https://www.bamsoftware.com/hacks/deflate.html

Naturally, running `scan -width $w +foo .' for {10..1000} doesn't cause
any problems, in C or en_GB.utf8 locale, but it seems quite possible to
me that the wcwidth() of a `mbtowc() < 0' could be -1, as above?

-- 
Cheers, Ralph.
https://plus.google.com/+RalphCorderoy

_______________________________________________
Nmh-workers mailing list
Nmh-workers(_at_)nongnu(_dot_)org
https://lists.nongnu.org/mailman/listinfo/nmh-workers

<Prev in Thread] Current Thread [Next in Thread>