nmh-workers
[Top] [All Lists]

Re: [Nmh-workers] mhshow -file /tmp (!)

2017-03-18 10:27:20
Hi Ken,

David's committed a directory test now, but I still think the underlying
cause is interesting, and some mess remains.

mhshow calls parse_mime()
parse_mime() calls get_content()
get_content() decides it's a message with a single text/plain part
(default)
Then the MIME display routines are called, and you end up in
open7Bit().

The part where YOU fail, "internal error (3)", I go past.

When Paul first reported the problem, I could re-create it and got the
"internal error".  Then when the next email arrived, I couldn't.  I can
create it consistently now depending on the directory I specify.

    $ mhshow -file /tmp


    $ mhshow -file /boot


    mhshow: internal error(3)
    $

On this (Arch, it's rather good) Linux, I see that

    429 read_more (m_getfld_state_t s) {
    443     num_read = fread (s->readpos, 1, MSG_INPUT_SIZE, s->iob);

does

    fread(0x15cd030, 1, 4096, 0x15d1790 <unfinished ...>
        SYS_fstat(3, 0x7fffa80952c0) = 0
        SYS_read(3, "", 4096) = -21 (EISDIR)
    <... fread resumed>) = 0

That causes Getc() to return EOF.  So m_getfld() return FILEEOF.  And
get_content() breaks its first loop on the first iteration.
ct->c_first_hf is still zero bytes, which the code assumes is a NULL
pointer, so that big loop is never entered.

We reach this epilogue and say the directory that yielded no bytes is
7-bit text/plain.

    547     /*
             * Check if we saw a Content-Type field.
             * If not, then assign a default value for
             * it, and the Init function.
             */
            if (!ct->c_ctline) {
    557         if (toplevel < 0) {
    562         } else {
                    /*
                     * Else default type is text/plain
                     */
                    if (get_ctinfo ("text/plain", ct, 0) == NOTOK)
                        goto out;
                    ct->c_type = CT_TEXT;
                    ct->c_ctinitfnx = InitText;
                }
            }

            /* Use default Transfer-Encoding, if necessary */
            if (!ct->c_celine) {
                ct->c_encoding = CE_7BIT;
                Init7Bit (ct);
            }

            return ct;

So far, similar behaviour and output can be seen with `mhshow -file
/dev/null' as that too yields no bytes.  Should an email with no headers
be an error at this point, instead of being blessed as text/plain?

So, why the different behaviour for /tmp v. /boot?  Ken pointed out the
`internal error(3)' test.

    2148     int cc, fd, len, own_ct_fp = 0;
    2238     if ((len = ct->c_end - ct->c_begin) < 0)

The values seen here are

    /tmp   ct->c_begin: 0  ct->c_end: 0
    /boot  ct->c_begin: 0  ct->c_end: 9223372036854775807

    $ dc <<<16o9223372036854775807p
    7FFFFFFFFFFFFFFF

Line 2148, quoted above, shows len is int, 32b here, so it gets the
bottom 32 bits of a large positive number in a buggy truncation and
becomes negative, -1.  -1 - 0 < 0 is true.

Why is c_end the maximum signed 64b for /boot?

    $ stat -c '%04D  %n' /etc/passwd / /home /tmp /boot
    0801  /etc/passwd
    0801  /
    0803  /home
    0024  /tmp
    0801  /boot
    $
    $ strace -e open,lseek perl -le \
    >     'for (@ARGV) {open(F, $_); sysseek F, 0, 2}' \
    >     /etc/passwd / /home /tmp /boot |&
    > egrep '^(open|lseek.*END)' |
    > grep -B1 END
    open("/etc/passwd", O_RDONLY)           = 3
    lseek(3, 0, SEEK_END)                   = 1713
    open("/", O_RDONLY)                     = 3
    lseek(3, 0, SEEK_END)                   = 9223372036854775807
    open("/home", O_RDONLY)                 = 3
    lseek(3, 0, SEEK_END)                   = 9223372036854775807
    open("/tmp", O_RDONLY)                  = 3
    lseek(3, 0, SEEK_END)                   = -1 EINVAL (Invalid argument)
    open("/boot", O_RDONLY)                 = 3
    lseek(3, 0, SEEK_END)                   = 9223372036854775807
    $

IIRC, this is valid POSIX.  :-)  I suspect Paul has a similar filesystem
arrangement for /tmp to me.

-- 
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>