about summary refs log tree commit diff
path: root/src/stdio
Commit message (Collapse)AuthorAgeFilesLines
* vfwprintf: honor field width with 'c' format typeA. Wilcox2018-08-281-1/+4
|
* set stream orientations in open_[w]memstreamRich Felker2018-08-282-0/+3
| | | | | | | | | | | | | | | | fundamentally there is no good reason these functions need to set an orientation (morally it should be possible to write a wchar_t[] memory stream using byte functions, or a char[] memory stream using wide functions), but it's a part of the specification that they do. aside from being able to inspect the orientation with fwide, failure to set the orientation in open_wmemstream is observable if the locale changes between open_wmemstream and the first operation on the stream; this is because the encoding rule (locale) for the stream is required to be bound at the time the stream becomes wide-oriented. for open_wmemstream, call fwide to avoid duplicating the logic for binding the encoding rule. for open_memstream it suffices just to set the mode field in the FILE struct.
* make fmemopen's w+ mode truncate the bufferRich Felker2018-08-281-0/+1
| | | | | | | | | | | | | the w+ mode is specified to "truncate the buffer contents". like most of fmemopen, exactly what this means is underspecified. mode w and w+ of course implicitly 'truncate' the buffer if a write from the initial position is flushed, so in order for this part of the text about w+ not to be spurious, it should be interpreted as requiring something else, and the obvious reasonable interpretation is that the truncation is immediately visible if you attempt to read from the stream or the buffer before writing/flushing. this interpretation agrees with reported conformance test failures.
* set errno when fileno is called on a FILE with no underlying fdRich Felker2018-08-281-4/+7
| | | | | | | | this is a POSIX requirement. also remove the gratuitous locking shenanigans and simply access f->fd under control of the lock. there is no advantage to not doing so, and it made the correctness non-obvious at best.
* fix printf precision specifier for hex floats on non-ld80 archsRich Felker2018-08-231-0/+1
| | | | | | | | | the code to perform rounding to the desired precision wrongly assumed the long double mantissa was an integral number of nibbles (hex digits) in length. this is true for 80-bit extended precision (64-bit mantissa) but not for double (53) or quad (113). scale the rounding value by 1<<(LDBL_MANT_DIG%4) to compensate.
* fix writes outside buffer by ungetc after setvbufRich Felker2018-07-131-1/+1
| | | | | | | | | commit 0b80a7b0404b6e49b0b724e3e3fe0ed5af3b08ef, which added non-stub setvbuf, applied the UNGET pushback adjustment to the size of the buffer passed in, but inadvertently omitted offsetting the start by the same amount, thereby allowing unget to clobber up to 8 bytes before the start of the buffer. this bug was introduced in the present release cycle; no releases are affected.
* setvbuf: minor comment typo fixWill Dietz2018-04-191-1/+1
|
* add support for caller-provided buffers to setvbufRich Felker2018-04-181-11/+14
|
* clean up allocation/setup logic for open_[w]memstreamRich Felker2018-04-182-38/+50
| | | | | bring these functions up to date with the current idioms we use/prefer in fmemopen and fopencookie.
* clean up allocation/setup logic for fmemopenRich Felker2018-04-181-21/+31
| | | | | | rather than manually performing pointer arithmetic to carve multiple objects out of one allocation, use a containing struct that encompasses them all.
* minor cleanup in fopencookieRich Felker2018-04-181-5/+2
| | | | | assign entire struct rather than member-at-a-time. don't repeat buffer sizes; always use sizeof to ensure consistency.
* refactor flockfile not to duplicate lock mechanism logicRich Felker2018-04-182-12/+14
|
* fix stdio lock dependency on read-after-free not faultingRich Felker2018-04-183-20/+24
| | | | | | | instead of using a waiters count, add a bit to the lock field indicating that the lock may have waiters. threads which obtain the lock after contending for it will perform a potentially-spurious wake when they release the lock.
* fix aliasing violations in fgetpos/fsetposRich Felker2018-02-242-2/+2
| | | | | | | | | | | | | add a member of appropriate type to the fpos_t union so that accesses are well-defined. use long long instead of off_t since off_t is not always exposed in stdio.h and there's no namespace-clean alias for it. access is still performed using pointer casts rather than by naming the union member as a matter of style; to the extent possible, the naming of fields in opaque types defined in the public headers is not treated as an API contract with the implementation. access via the pointer cast is valid as long as the union has a member of matching type.
* in vswprintf, initialize the FILE rather than memset-and-assignRich Felker2018-02-241-9/+8
| | | | | this is the idiom that's used elsewhere and should be more efficient or at least no worse.
* remove unused MIN macro from getdelim source fileRich Felker2018-02-241-2/+0
|
* remove useless null check before call to free in fcloseRich Felker2018-02-241-1/+1
|
* remove useless and confusing parentheses in stdio __towrite functionRich Felker2018-02-241-1/+1
| | | | | | they seem to be relics of e3cd6c5c265cd481db6e0c5b529855d99f0bda30 where this code was refactored from a check that previously masked against (F_ERR|F_NOWR) instead of just F_NOWR.
* avoid use of readv syscall in __stdio_read backend when not neededRich Felker2018-02-241-1/+2
| | | | | | | | formally, calling readv with a zero-length first iov component should behave identically to calling read on just the second component, but presence of a zero-length iov component has triggered bugs in some kernels and performs significantly worse than a simple read on some file types.
* consistently return number of bytes read from stdio read backendRich Felker2018-02-242-2/+2
| | | | | | | | | | the stdio FILE read backend's return type is size_t, not ssize_t, and all of the special (non-fd-backed) FILE types already return the number of bytes read (zero) on error or eof. only __stdio_read leaked a syscall error return into its return value. fread had a workaround for this behavior going all the way back to the original check-in. remove the workaround since it's no longer needed.
* remove obfuscated flags bit-twiddling logic in __stdio_readRich Felker2018-02-241-1/+1
| | | | | replace with simple conditional that doesn't rely on assumption that cnt is either 0 or -1.
* fix incorrect overflow check for allocation in fmemopenRich Felker2018-02-111-1/+1
| | | | | | | | | | | | | | when a null buffer pointer is passed to fmemopen, requesting it allocate its own memory buffer, extremely large size arguments near SIZE_MAX could overflow and result in underallocation. this results from omission of the size of the cookie structure in the overflow check but inclusion of it in the calloc call. instead of accounting for individual small contributions to the total allocation size needed, simply reject sizes larger than PTRDIFF_MAX, which will necessarily fail anyway. then adding arbitrary fixed-size structures is safe without matching up the expressions in the comparison and the allocation.
* fix printf alt-form octal with value 0 and no explicit precisionRich Felker2018-01-101-2/+2
| | | | | | | | | | | | | | | | | | commit 78897b0dc00b7cd5c29af5e0b7eebf2396d8dce0 wrongly simplified Dmitry Levin's original submitted patch fixing alt-form octal with the zero flag and field width present, omitting the special case where the value is zero. as a result, printf("%#o",0) wrongly prints "00" rather than "0". the logic prior to this commit was actually better, in that it was aligned with how the alt-form flag (#) for printf is specified ("it shall increase the precision"). at the time there was no good way to avoid the zero flag issue with the old logic, but commit 167dfe9672c116b315e72e57a55c7769f180dffa added tracking of whether an explicit precision was provided. revert commit 78897b0dc00b7cd5c29af5e0b7eebf2396d8dce0 and switch to using the explicit precision indicator for suppressing the zero flag.
* revise the definition of multiple basic locks in the codeJens Gustedt2018-01-091-1/+1
| | | | In all cases this is just a change from two volatile int to one.
* implement the fopencookie extension to stdioWilliam Pitcock2017-12-061-0/+138
| | | | | | | | | | | | | | | | | | | | | | | | notes added by maintainer: this function is a GNU extension. it was chosen over the similar BSD function funopen because the latter depends on fpos_t being an arithmetic type as part of its public API, conflicting with our definition of fpos_t and with the intent that it be an opaque type. it was accepted for inclusion because, despite not being widely used, it is usually very difficult to extricate software using it from the dependency on it. calling pattern for the read and write callbacks is not likely to match glibc or other implementations, but should work with any reasonable callbacks. in particular the read function is never called without at least one byte being needed to satisfy its caller, so that spurious blocking is not introduced. contracts for what callbacks called from inside libc/stdio can do are always complicated, and at some point still need to be specified explicitly. at the very least, the callbacks must return or block indefinitely (they cannot perform nonlocal exits) and they should not make calls to stdio using their own FILE as an argument.
* make fgetwc handling of encoding errors consistent with/without bufferRich Felker2017-11-201-14/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | previously, fgetwc left all but the first byte of an illegal sequence unread (available for subsequent calls) when reading out of the FILE buffer, but dropped all bytes contibuting to the error when falling back to reading a byte at a time. neither behavior was ideal. in the buffered case, each malformed character produced one error per byte, rather than one per character. in the unbuffered case, consuming the last byte that caused the transition from "incomplete" to "invalid" state potentially dropped (and produced additional spurious encoding errors for) the next valid character. to handle both cases uniformly without duplicate code, revise the buffered case to only cover situations where a complete and valid character is present in the buffer, and fall back to byte-at-a-time for all other cases. this allows using mbtowc (stateless) instead of mbrtowc, which may slightly improve performance too. when an encoding error has been hit in the byte-at-a-time case, leave the final byte that produced the error unread (via ungetc) except in the case of single-byte errors (for UTF-8, bytes c0, c1, f5-ff, and continuation bytes with no lead byte). single-byte errors are fully consumed so as not to leave the caller in an infinite loop repeating the same error. none of these changes are distinguished from a conformance standpoint, since the file position is unspecified after encoding errors. they are intended merely as QoI/consistency improvements.
* fix treatment by fgetws of encoding errors as eofRich Felker2017-11-201-1/+6
| | | | | | | | | | | | | fgetwc does not set the stream's error indicator on encoding errors, making ferror insufficient to distinguish between error and eof conditions. feof is also insufficient, since it will return true if the file ended with a partial character encoding error. whether fgetwc should be setting the error indicator itself is a question with conflicting answers. the POSIX text for the function states it as a requirement, but the ISO C text seems to require that it not. this may be revisited in the future based on the outcome of Austin Group issue #1170.
* fix fgetwc when decoding a character that crosses buffer boundarySzabolcs Nagy2017-11-181-0/+1
| | | | | Update the buffer position according to the bytes consumed into st when decoding an incomplete character at the end of the buffer.
* handle whitespace before %% in scanfBartosz Brachaczek2017-09-042-5/+13
| | | | | this is mandated by C and POSIX standards and is in accordance with glibc behavior.
* fix unsynchronized access to FILE structure in fflush(0)Rich Felker2017-08-291-1/+4
| | | | | | commit c002668eb0352e619ea7064e4940b397b4a6e68d inadvertently moved the check for unflushed write buffer outside of the scope of the existing lock.
* remove ineffective compiler assist from printfAlexander Monakov2017-07-042-4/+0
| | | | | | The switch statement has no 'default:' case and the function ends immediately following the switch, so the extra comparison did not communicate any extra information to the compiler.
* reapply va_arg hacks removal to wprintfAlexander Monakov2017-07-041-26/+1
| | | | | commit 58e2396a9aa23c132faf4198ca4d779c84955b38 missed that the same code was duplicated in implementation of vfwprintf.
* remove va_arg hacks in printf core with undefined behaviorRich Felker2017-04-221-26/+1
| | | | | | | | | | | | | | the code being removed was written to optimize for size assuming the compiler cannot collapse code paths for different types with the same underlying representation. modern compilers sometimes succeed in making this optimization themselves, but either way it's a small size difference and not worth the source-level complexity or the UB involved in this hack. some incorrect use of va_arg still remains, particularly use of void * where the actual argument has a different pointer type. fixing this requires some actual code additions, rather than just removing cruft, so I'm leaving it to be done later as a separate commit.
* fix wide scanf's use of a compound literal past its lifetimeRich Felker2017-03-141-1/+2
|
* fix swprintf internal buffer state and error handlingRich Felker2016-11-071-1/+8
| | | | | | | | the swprintf write callback never reset its buffer pointers, so after its 256-byte buffer filled up, it would keep repeating those bytes over and over in the output until the destination buffer filled up. it also failed to set the error indicator for the stream on EILSEQ, potentially allowing output to continue after the error.
* redesign snprintf without undefined behaviorRich Felker2016-10-211-25/+38
| | | | | | | | | | | | | the old snprintf design setup the FILE buffer pointers to point directly into the destination buffer; if n was actually larger than the buffer size, the pointer arithmetic to compute the buffer end pointer was undefined. this affected sprintf, which is implemented in terms of snprintf, as well as some unusual but valid direct uses of snprintf. instead, setup the FILE as unbuffered and have its write function memcpy to the destination. the printf core sets up its own temporary buffer for unbuffered streams.
* fix float formatting of some exact halfway casesSzabolcs Nagy2016-10-201-1/+2
| | | | | | | | in nearest rounding mode exact halfway cases were not following the round to even rule if the rounding happened at a base 1000000000 digit boundary of the internal representation and the previous digit was odd. e.g. printf("%.0f", 1.5) printed 1 instead of 2.
* fix integer overflows and uncaught EOVERFLOW in printf coreRich Felker2016-10-202-46/+89
| | | | | | | | | | | | | | | | | | | | | | | | | | | | this patch fixes a large number of missed internal signed-overflow checks and errors in determining when the return value (output length) would exceed INT_MAX, which should result in EOVERFLOW. some of the issues fixed were reported by Alexander Cherepanov; others were found in subsequent review of the code. aside from the signed overflows being undefined behavior, the following specific bugs were found to exist in practice: - overflows computing length of floating point formats with huge explicit precisions, integer formats with prefix characters and huge explicit precisions, or string arguments or format strings longer than INT_MAX, resulted in wrong return value and wrong %n results. - literal width and precision values outside the range of int were misinterpreted, yielding wrong behavior in at least one well-defined case: string formats with precision greater than INT_MAX were sometimes truncated. - in cases where EOVERFLOW is produced, incorrect values could be written for %n specifiers past the point of exceeding INT_MAX. in addition to fixing these bugs, we now stop producing output immediately when output length would exceed INT_MAX, rather than continuing and returning an error only at the end.
* fix integer overflow in float printf needed-precision computationRich Felker2016-10-191-1/+1
| | | | | | | | | | | | | | if the requested precision is close to INT_MAX, adding LDBL_MANT_DIG/3+8 overflows. in practice the resulting undefined behavior manifests as a large negative result, which is then used to compute the new end pointer (z) with a wildly out-of-bounds value (more overflow, more undefined behavior). the end result is at least incorrect output and character count (return value); worse things do not seem to happen, but detailed analysis has not been done. this patch fixes the overflow by performing the intermediate computation as unsigned; after division by 9, the final result necessarily fits in int.
* simplify/refactor fflush and make fflush_unlocked an alias for fflushRich Felker2016-09-181-30/+23
| | | | | | | | | | | | | | | | | | previously, fflush_unlocked was an alias for an internal backend that was called by fflush, either for its argument or in a loop for each file if a null pointer was passed. since the logic for the latter was in the main fflush function, fflush_unlocked crashed when passed a null pointer, rather than flushing all open files. since fflush_unlocked is not a standard function and has no specification, it's not clear whether it should be expected to accept null pointers like fflush does, but a reasonable argument could be made that it should. this patch eliminates the helper function, simplifying fflush, and makes fflush_unlocked an alias for fflush, which is valid because the two functions agree in their behavior in all cases where their behavior is defined (the unlocked version has undefined behavior if another thread could hold locks).
* fix printf regression with alt-form octal, zero flag, and field widthRich Felker2016-09-161-1/+1
| | | | | | | | | | commit b91cdbe2bc8b626aa04dc6e3e84345accf34e4b1, in fixing another issue, changed the logic for how alt-form octal adds the leading zero to adjust the precision rather than using a prefix character. this wrongly suppressed the zero flag by mimicing an explicit precision given by the format string. switch back to using a prefix character. based on bug report and patch by Dmitry V. Levin, but simplified.
* fix FILE buffer underflow in ungetwcRich Felker2016-04-261-3/+3
| | | | | | | | | | | | | | | | | | | | | commit 7e816a6487932cbb3cb71d94b609e50e81f4e5bf (version 1.1.11 release cycle) moved the code that performs wchar_t to multibyte conversion across code that used the resulting length in bytes, thereby breaking the unget buffer space check in ungetwc and clobbering up to three bytes below the start of the buffer. for allocated FILEs (all read-enabled FILEs except stdin), the underflow clobbers at most the FILE-specific locale pointer. no stores are performed through this pointer, but subsequent loads may result in a crash or mismatching encoding rule (UTF-8 multibyte vs byte-based). for stdin, the buffer lies in .bss and the underflow may clobber another object. in practice, for libc.so the adjacent object seems to be stderr's buffer, which is completely unused, but this could vary with linking options, or when static linking. applications which do not attempt to use more than one character of ungetwc pushback, or which do not use ungetwc, are not affected.
* fix undefined pointer comparison in stdio-internal __toreadRich Felker2016-03-281-1/+1
| | | | | | | | | | | | | | the comparison f->wpos > f->buf has undefined behavior when f->wpos is a null pointer, despite the intuition (and actual compiler behavior, for all known compilers) being that NULL > ptr is false for all valid pointers ptr. the purpose of the comparison is to determine if the write buffer is non-empty, and the idiom used elsewhere for that is comparison against f->wbase, which is either a null pointer when not writing, or equal to f->buf when writing. in the former case, both f->wpos and f->wbase are null; in the latter they are both non-null and point into the same array.
* fix padding string formats to width in wide printf variantsRich Felker2016-03-161-4/+4
| | | | | | | the idiom fprintf(f, "%.*s", n, "") was wrongly used in vfwprintf as a means of producing n spaces; instead it produces no output. the correct form is fprintf(f, "%*s", n, ""), using width instead of precision, since for %s the later is a maximum rather than a minimum.
* fix assumption in fputs that fwrite returning 0 implies an errorRich Felker2016-02-161-1/+2
| | | | | | | | | | internally, the idiom of passing nmemb=1 to fwrite and interpreting the return value of fwrite (which is necessarily 0 or 1) as failure/success is fairly widely used. this is not correct, however, when the size argument is unknown and may be zero, since C requires fwrite to return 0 in that special case. previously fwrite always returned nmemb on success, but this was changed for conformance with ISO C by commit 500c6886c654fd45e4926990fee2c61d816be197.
* fix return value for fread/fwrite when size argument is 0Rich Felker2016-02-102-0/+2
| | | | | | | when the size argument was zero but nmemb was nonzero, these functions were returning nmemb, despite no data having been written. conceptually this is not wrong, but the standard requires a return value of zero in this case.
* fix failed write reporting by fwrite in line-buffered modeRich Felker2016-02-101-2/+2
| | | | | | | | | | | | when a write error occurred while flushing output due to a newline, fwrite falsely reported all bytes up to and including the newline as successfully written. in general, due to buffering such "spurious success" returns are acceptable for stdio; however for line-buffered mode it was subtly wrong. errors were still visible via ferror() or as a short-write return if there was more data past the newline that should have been written, but since the contract for line-buffered mode is that everything up through the newline be written out immediately, a discrepency was observable in the actual file contents.
* fix overly pessimistic realloc strategy in getdelimRich Felker2015-12-201-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | previously, getdelim was allocating twice the space needed every time it expanded its buffer to implement exponential buffer growth (in order to avoid quadratic run time). however, this doubling was performed even when the final buffer length needed was already known, which is the common case that occurs whenever the delimiter is in the FILE's buffer. this patch makes two changes to remedy the situation: 1. over-allocation is no longer performed if the delimiter has already been found when realloc is needed. 2. growth factor is reduced from 2x to 1.5x to reduce the relative excess allocation in cases where the delimiter is not initially in the buffer, including unbuffered streams. in theory these changes could lead to quadratic time if the same buffer is reused to process a sequence of lines successively increasing in length, but once this length exceeds the stdio buffer size, the delimiter will not be found in the buffer right away and exponential growth will still kick in.
* avoid updating caller's size when getdelim fails to reallocRich Felker2015-12-191-5/+6
| | | | | | | | | | | getdelim was updating *n, the caller's stored buffer size, before calling realloc. if getdelim then failed due to realloc failure, the caller would see in *n a value larger than the actual size of the allocated block, and use of that value is unsafe. in particular, passing it again to getdelim is unsafe. now, temporary storage is used for the desired new size, and *n is not written until realloc succeeds.
* fix single-byte overflow of malloc'd buffer in getdelimRich Felker2015-10-241-1/+1
| | | | | | | | | | the buffer enlargement logic here accounted for the terminating null byte, but not for the possibility of hitting the delimiter in the buffer-refill code path that uses getc_unlocked, in which case two additional bytes (the delimiter and the null termination) are written without another chance to enlarge the buffer. this patch and the corresponding bug report are by Felix Janda.