NetBSD Problem Report #47396

From www@NetBSD.org  Thu Jan  3 18:55:55 2013
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	by www.NetBSD.org (Postfix) with ESMTP id C8A0763E965
	for <gnats-bugs@gnats.NetBSD.org>; Thu,  3 Jan 2013 18:55:54 +0000 (UTC)
Message-Id: <20130103185553.F2B6B63E965@www.NetBSD.org>
Date: Thu,  3 Jan 2013 18:55:53 +0000 (UTC)
From: sdaoden@gmail.com
Reply-To: sdaoden@gmail.com
To: gnats-bugs@NetBSD.org
Subject: mail(1) may falsely use QP for fails with embedded NULs
X-Send-Pr-Version: www-1.0

>Number:         47396
>Category:       bin
>Synopsis:       mail(1) may falsely use QP for fails with embedded NULs
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jan 03 19:00:01 +0000 2013
>Closed-Date:    Fri Jan 04 08:17:08 +0000 2013
>Last-Modified:  Fri Jan 04 08:17:08 +0000 2013
>Originator:     Steffen
>Release:        git trunk sources
>Organization:
>Environment:
NetBSD 6.0 RELEASE
>Description:
The problem is that mime_attach.c:content_encoding_core() bails out for a character that has the high bit set.
If the MIME part is_text(), then this will force QP to be used, only otherwise it's base64.
If the file contains a NUL byte after this very character then the wrong encoding is used.  (Situation is not so bad since libmagic(3) examines the filecontent before, though.  I.e., NetBSD mail(1) examines the filecontent multiple times before use ;-))
>How-To-Repeat:
Try to fix your baby and feed shitty examples through poor software.
>Fix:
This also includes the fix for bin/47395.

--- mime_attach.c.orig  2013-01-03 19:26:26.000000000 +0100
+++ mime_attach.c       2013-01-03 19:42:09.000000000 +0100
@@ -224,43 +224,42 @@ is_text(const char *ctype)
 static const char *
 content_encoding_core(void *fh, const char *ctype)
 {
+       enum {
+               _CLEAN  = 0,
+               _ENDWS  = 1<<0,
+               _CTRLC  = 1<<1,
+               _8BIT   = 1<<2,
+               _LONGL  = 1<<3
+       } state = _CLEAN;
+       size_t maxlen = line_limit(), curlen;
        int c, lastc;
-       int ctrlchar, endwhite;
-       size_t curlen, maxlen;

-       curlen = 0;
-       maxlen = 0;
-       ctrlchar = 0;
-       endwhite = 0;
-       lastc = EOF;
-       while ((c = fgetc(fh)) != EOF) {
+       for (curlen = 0, lastc = EOF; (c = fgetc(fh)) != EOF; lastc = c) {
                curlen++;

-               if (c == '\0' || (lastc == '\r' && c != '\n'))
+               if (c == '\0')
                        return MIME_TRANSFER_BASE64;

                if (c > 0x7f) {
-                       if (is_text(ctype))
-                               return MIME_TRANSFER_QUOTED;
-                       else
+                       if (! is_text(ctype))
                                return MIME_TRANSFER_BASE64;
+                       state |= _8BIT;
+                       continue;
                }
                if (c == '\n') {
                        if (is_WSP(lastc))
-                               endwhite = 1;
+                               state |= _ENDWS;
                        if (curlen > maxlen)
-                               maxlen = curlen;
+                               state |= _LONGL;
                        curlen = 0;
                }
-               else if ((c < 0x20 && c != '\t') || c == 0x7f)
-                       ctrlchar = 1;
-
-               lastc = c;
+               else if ((c < 0x20 && c != '\t') || c == 0x7f || lastc == '\r')
+                       state |= _CTRLC;
        }
        if (lastc == EOF) /* no characters read */
                return MIME_TRANSFER_7BIT;

-       if (lastc != '\n' || ctrlchar || endwhite || maxlen > line_limit())
+       if (lastc != '\n' || state != _CLEAN)
                return MIME_TRANSFER_QUOTED;

        return MIME_TRANSFER_7BIT;

>Release-Note:

>Audit-Trail:
From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/47396 CVS commit: src/usr.bin/mail
Date: Thu, 3 Jan 2013 20:54:55 -0500

 Module Name:	src
 Committed By:	christos
 Date:		Fri Jan  4 01:54:55 UTC 2013

 Modified Files:
 	src/usr.bin/mail: mime_attach.c

 Log Message:
 PR/47396: Steffen: mail(1) may falsely use quoted-printable for files with
 embedded NULs
 --- mime_attach.c.orig  2013-01-03 19:26:26.000000000 +0100
 +++ mime_attach.c       2013-01-03 19:42:09.000000000 +0100
 @@ -224,43 +224,42 @@ is_text(const char *ctype)
  static const char *
  content_encoding_core(void *fh, const char *ctype)
  {
 +       enum {
 +               _CLEAN  = 0,
 +               _ENDWS  = 1<<0,
 +               _CTRLC  = 1<<1,
 +               _8BIT   = 1<<2,
 +               _LONGL  = 1<<3
 +       } state = _CLEAN;
 +       size_t maxlen = line_limit(), curlen;
         int c, lastc;
 -       int ctrlchar, endwhite;
 -       size_t curlen, maxlen;

 -       curlen = 0;
 -       maxlen = 0;
 -       ctrlchar = 0;
 -       endwhite = 0;
 -       lastc = EOF;
 -       while ((c = fgetc(fh)) != EOF) {
 +       for (curlen = 0, lastc = EOF; (c = fgetc(fh)) != EOF; lastc = c) {
                 curlen++;

 -               if (c == '\0' || (lastc == '\r' && c != '\n'))
 +               if (c == '\0')
                         return MIME_TRANSFER_BASE64;

                 if (c > 0x7f) {
 -                       if (is_text(ctype))
 -                               return MIME_TRANSFER_QUOTED;
 -                       else
 +                       if (! is_text(ctype))
                                 return MIME_TRANSFER_BASE64;
 +                       state |= _8BIT;
 +                       continue;
                 }
                 if (c == '\n') {
                         if (is_WSP(lastc))
 -                               endwhite = 1;
 +                               state |= _ENDWS;
                         if (curlen > maxlen)
 -                               maxlen = curlen;
 +                               state |= _LONGL;
                         curlen = 0;
                 }
 -               else if ((c < 0x20 && c != '\t') || c == 0x7f)
 -                       ctrlchar = 1;
 -
 -               lastc = c;
 +               else if ((c < 0x20 && c != '\t') || c == 0x7f || lastc == '\r')
 +                       state |= _CTRLC;
         }
         if (lastc == EOF) /* no characters read */
                 return MIME_TRANSFER_7BIT;

 -       if (lastc != '\n' || ctrlchar || endwhite || maxlen > line_limit())
 +       if (lastc != '\n' || state != _CLEAN)
                 return MIME_TRANSFER_QUOTED;

         return MIME_TRANSFER_7BIT;


 To generate a diff of this commit:
 cvs rdiff -u -r1.15 -r1.16 src/usr.bin/mail/mime_attach.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: open->closed
State-Changed-By: wiz@NetBSD.org
State-Changed-When: Fri, 04 Jan 2013 08:17:08 +0000
State-Changed-Why:
christos committed it. Thanks!


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.