cli/show: avoid empty write to stdout in format_part_raw
authorDavid Bremner <david@tethera.net>
Sat, 4 May 2019 22:29:08 +0000 (19:29 -0300)
committerDavid Bremner <david@tethera.net>
Sun, 5 May 2019 11:01:17 +0000 (08:01 -0300)
Previously if the input was exactly a multiple of the internal buffer
size, notmuch would attempt to fwrite nothing to stdout, but still
expected fwrite to return 1, causing a failure that looked like this:

  $ notmuch show --format=raw id:87o96f1cya.fsf@codeaurora.org
    ...entire message shown as expected..
  Error: Write failed
  $ echo $?
  1

To fix the problem don't call fwrite at all when there's nothing to
write.

Amended by db: add some tests of message sizes likely to cause this
problem.

notmuch-show.c
test/T210-raw.sh

index c3a3783a4094c952f61b567907b87f658a1381ab..98b8535265f997c5c7651527a361ac2bbe92a6d5 100644 (file)
@@ -851,7 +851,7 @@ format_part_raw (unused (const void *ctx), unused (sprinter_t *sp),
                return NOTMUCH_STATUS_FILE_ERROR;
            }
 
-           if (fwrite (buf, size, 1, stdout) != 1) {
+           if (size > 0 && fwrite (buf, size, 1, stdout) != 1) {
                fprintf (stderr, "Error: Write failed\n");
                fclose (file);
                return NOTMUCH_STATUS_FILE_ERROR;
index 99fdef72e634fad35e91801e2f292a749c615c76..85e707d4741c8eb441535ac6a9a1fd7b9496764a 100755 (executable)
@@ -30,4 +30,38 @@ Date: GENERATED_DATE
 
 This is just a test message (#2)"
 
+test_python <<EOF
+from email.message import EmailMessage
+for pow in range(10,21):
+    size = 2 ** pow
+    msg = EmailMessage()
+    msg['Subject'] = 'message with {:07d} bytes'.format(size)
+    msg['From'] = 'Notmuch Test Suite <test_suite@notmuchmail.org>'
+    msg['To'] = msg['From']
+    msg['Message-Id'] = 'size-{:07d}@notmuch-test-suite'.format(size)
+    content = ""
+    msg.set_content("")
+    padding = size - len(bytes(msg))
+    lines = []
+    while padding > 0:
+        line = '.' * min(padding, 72)
+        lines.append(line)
+        padding = padding - len(line) - 1
+    content ='\n'.join(lines)
+    msg.set_content(content)
+    with open('mail/size-{:07d}'.format(size), 'wb') as f:
+        f.write(bytes(msg))
+EOF
+
+notmuch new --quiet
+
+for pow in {10..20}; do
+    printf -v size "%07d" $((2**$pow))
+    test_begin_subtest "content, message of size $size"
+    notmuch show --format=raw subject:$size > OUTPUT
+    test_expect_equal_file mail/size-$size OUTPUT
+    test_begin_subtest "return value, message of size $size"
+    test_expect_success  "notmuch show --format=raw subject:$size > /dev/null"
+done
+
 test_done