mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Fix vfprintf and derived functions not handling write errors (#798)
The C standard states: > The fprintf function returns the number of characters transmitted, > or a negative value if an output or encoding error occurred or if > the implementation does not support a specified width length > modifier. - C Standard, 7.23.6.1.15. The fprintf function However, cosmopolitan fails to return a negative value in the case of an output error, meaning that a program such as: #include <stdio.h> int main() { FILE *fp = fopen("/dev/full", "w"); setbuf(fp, NULL); printf("fprintf: %d\n", fprintf(fp, "test\n")); printf("fflush: %d\n", fflush(fp)); } will, under cosmopolitan, print that no error occured in either of the calls to fprintf and fflush. This patch fixes this, along with the associated GitHub issue, https://github.com/jart/cosmopolitan/issues/784
This commit is contained in:
parent
221adfa606
commit
9c6d78c26d
3 changed files with 38 additions and 1 deletions
|
@ -44,7 +44,7 @@ static int vfprintfputchar(const char *s, struct state *t, size_t n) {
|
||||||
} else {
|
} else {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
34
test/libc/fmt/fprintf_test.c
Normal file
34
test/libc/fmt/fprintf_test.c
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2023 Gabriel Ravier │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
|
TEST(fprintf, testWriteError) {
|
||||||
|
// Only Linux, NetBSD and FreeBSD are known to have /dev/full
|
||||||
|
if (!IsLinux() && !IsNetbsd() && !IsFreebsd()) return;
|
||||||
|
|
||||||
|
FILE *fp = fopen("/dev/full", "w");
|
||||||
|
ASSERT_NE(fp, NULL);
|
||||||
|
|
||||||
|
setbuf(fp, NULL);
|
||||||
|
ASSERT_LT(fprintf(fp, "test"), 0);
|
||||||
|
|
||||||
|
ASSERT_EQ(fclose(fp), 0);
|
||||||
|
}
|
|
@ -55,6 +55,9 @@ $(TEST_LIBC_FMT_OBJS): private \
|
||||||
DEFAULT_CCFLAGS += \
|
DEFAULT_CCFLAGS += \
|
||||||
-fno-builtin
|
-fno-builtin
|
||||||
|
|
||||||
|
o/$(MODE)/test/libc/fmt/fprintf_test.com.runs: \
|
||||||
|
private .UNVEIL += w:/dev/full
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/test/libc/fmt
|
.PHONY: o/$(MODE)/test/libc/fmt
|
||||||
o/$(MODE)/test/libc/fmt: \
|
o/$(MODE)/test/libc/fmt: \
|
||||||
$(TEST_LIBC_FMT_BINS) \
|
$(TEST_LIBC_FMT_BINS) \
|
||||||
|
|
Loading…
Add table
Reference in a new issue