mirror of
				https://github.com/jart/cosmopolitan.git
				synced 2025-10-26 11:10:58 +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 { | ||||
|     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 +=				\
 | ||||
| 		-fno-builtin | ||||
| 
 | ||||
| o/$(MODE)/test/libc/fmt/fprintf_test.com.runs:		\ | ||||
| 	private .UNVEIL += w:/dev/full | ||||
| 
 | ||||
| .PHONY: o/$(MODE)/test/libc/fmt | ||||
| o/$(MODE)/test/libc/fmt:				\ | ||||
| 		$(TEST_LIBC_FMT_BINS)			\
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue