<feed xmlns='http://www.w3.org/2005/Atom'>
<title>musl/src/stdio, branch master</title>
<subtitle>musl - an implementation of the standard library for Linux-based systems</subtitle>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/'/>
<entry>
<title>ftello: report overflow in buffered stream position</title>
<updated>2026-08-14T15:41:59+00:00</updated>
<author>
<name>Matthias Goergens</name>
<email>matthias.goergens@gmail.com</email>
</author>
<published>2026-08-05T07:52:01+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=4a0406c85122cf0ea19a572590d4473e9d124ff7'/>
<id>4a0406c85122cf0ea19a572590d4473e9d124ff7</id>
<content type='text'>
ftello adds pending buffered output to the position reported by the
underlying seek operation. Near LLONG_MAX, the addition can overflow
signed off_t and return an apparently successful negative position.

Check that the buffered-byte count fits before adding it. Fail with
EOVERFLOW when the logical position cannot be represented.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
ftello adds pending buffered output to the position reported by the
underlying seek operation. Near LLONG_MAX, the addition can overflow
signed off_t and return an apparently successful negative position.

Check that the buffered-byte count fits before adding it. Fail with
EOVERFLOW when the logical position cannot be represented.
</pre>
</div>
</content>
</entry>
<entry>
<title>fseeko: avoid overflow adjusting relative seek offset</title>
<updated>2026-08-14T15:41:57+00:00</updated>
<author>
<name>Matthias Goergens</name>
<email>matthias.goergens@gmail.com</email>
</author>
<published>2026-08-05T07:52:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=30cc6422bc614d289630917cdd648805185b01ed'/>
<id>30cc6422bc614d289630917cdd648805185b01ed</id>
<content type='text'>
For SEEK_CUR, fseeko subtracts the unread input-buffer length from the
caller's offset before invoking the underlying seek operation. A valid
LLONG_MIN offset therefore overflows before the seek can reject the
unrepresentable logical result.

Detect the underflow and fail with EOVERFLOW without flushing or
discarding the stream's buffers.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
For SEEK_CUR, fseeko subtracts the unread input-buffer length from the
caller's offset before invoking the underlying seek operation. A valid
LLONG_MIN offset therefore overflows before the seek can reject the
unrepresentable logical result.

Detect the underflow and fail with EOVERFLOW without flushing or
discarding the stream's buffers.
</pre>
</div>
</content>
</entry>
<entry>
<title>stdio: avoid invalid pointer arithmetic in fputwc</title>
<updated>2026-08-05T18:30:33+00:00</updated>
<author>
<name>Matthias Goergens</name>
<email>matthias.goergens@gmail.com</email>
</author>
<published>2026-08-05T07:51:49+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=e9ac48d226aa1fa7a0176f1946b277e70fbd783a'/>
<id>e9ac48d226aa1fa7a0176f1946b277e70fbd783a</id>
<content type='text'>
Fresh writable streams use null wpos and wend pointers until output is
initialized. The non-ASCII path adds MB_LEN_MAX to wpos before comparing
it with wend, which is invalid for a null pointer. The addition can also
form a pointer beyond one past the buffer when little space remains.

First require an active output buffer. Then compare the defined
difference between its pointers. Preserve the existing strict capacity
test and use the normal write fallback otherwise.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Fresh writable streams use null wpos and wend pointers until output is
initialized. The non-ASCII path adds MB_LEN_MAX to wpos before comparing
it with wend, which is invalid for a null pointer. The addition can also
form a pointer beyond one past the buffer when little space remains.

First require an active output buffer. Then compare the defined
difference between its pointers. Preserve the existing strict capacity
test and use the normal write fallback otherwise.
</pre>
</div>
</content>
</entry>
<entry>
<title>fix toctou race in popen children's closing of other popen pipes</title>
<updated>2026-07-28T23:26:37+00:00</updated>
<author>
<name>Rich Felker</name>
<email>dalias@aerifal.cx</email>
</author>
<published>2026-07-28T23:26:37+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=f21a96538f78fa8e2040831b4209b35f2fb581da'/>
<id>f21a96538f78fa8e2040831b4209b35f2fb581da</id>
<content type='text'>
since commit e1a51185ceb4386481491e11f6dd39569b9e54f7, popen obeys an
obscure historical requirement to implement a sort of pseudo-cloexec
behavior for other pipe streams obtained by popen. but since popen
uses posix_spawn (and thereby posix_spawn file actions) internally,
the time of check for other pipe streams is separated from the time of
closure.

this was intended to be addressed by popen holding the open file list
lock across posix_spawn, but pclose (via fclose) closes the file
descriptor before taking the open file list lock, only using the lock
for updating the linked list pointers. this is to avoid serializing
fclose operations across the entire process, since in general close
may be a blocking operation.

multiple solutions to this problem were considered, but the simplest
and least invasive is conditionally taking the open file list lock
early for popen streams -- that is, for FILE streams where the
pipe_pid member is nonzero. since the file descriptor refers to a
pipe, closing it is a simple, nonblocking operation, and the only cost
is the time spent entering and leaving kernelspace while the lock is
held.

since individual FILE locks cannot be held while taking the open file
list lock (this would violate lock order protocol and produce
deadlocks), the FILE lock must be released after fflush but before the
ofl lock is taken. there is no point in retaking the lock afterwards,
since the FILE pointer is no longer valid and any further use by the
application would be undefined. so, simply let fflush do the locking.

note that the early return path (F_PERM) is not reachable for popen
streams, only for stdin/stdout/stderr, which are always normal FILEs.
thus, it does not provide a code path to return with the ofl lock
still held.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
since commit e1a51185ceb4386481491e11f6dd39569b9e54f7, popen obeys an
obscure historical requirement to implement a sort of pseudo-cloexec
behavior for other pipe streams obtained by popen. but since popen
uses posix_spawn (and thereby posix_spawn file actions) internally,
the time of check for other pipe streams is separated from the time of
closure.

this was intended to be addressed by popen holding the open file list
lock across posix_spawn, but pclose (via fclose) closes the file
descriptor before taking the open file list lock, only using the lock
for updating the linked list pointers. this is to avoid serializing
fclose operations across the entire process, since in general close
may be a blocking operation.

multiple solutions to this problem were considered, but the simplest
and least invasive is conditionally taking the open file list lock
early for popen streams -- that is, for FILE streams where the
pipe_pid member is nonzero. since the file descriptor refers to a
pipe, closing it is a simple, nonblocking operation, and the only cost
is the time spent entering and leaving kernelspace while the lock is
held.

since individual FILE locks cannot be held while taking the open file
list lock (this would violate lock order protocol and produce
deadlocks), the FILE lock must be released after fflush but before the
ofl lock is taken. there is no point in retaking the lock afterwards,
since the FILE pointer is no longer valid and any further use by the
application would be undefined. so, simply let fflush do the locking.

note that the early return path (F_PERM) is not reachable for popen
streams, only for stdin/stdout/stderr, which are always normal FILEs.
thus, it does not provide a code path to return with the ofl lock
still held.
</pre>
</div>
</content>
</entry>
<entry>
<title>fix fmemopen write-mode streams clobbering final byte with null</title>
<updated>2026-05-05T23:49:32+00:00</updated>
<author>
<name>Rich Felker</name>
<email>dalias@aerifal.cx</email>
</author>
<published>2026-05-05T23:49:32+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=bb4b4102461acfbf77da759ca3a6deb555f3da3b'/>
<id>bb4b4102461acfbf77da759ca3a6deb555f3da3b</id>
<content type='text'>
commit d2e061a2bd3f7674cfef2e2217e0695419041b5e wrongly added this
case based on a misreading of the standard text regarding null
termination in write/update modes. apparently, the condition "if it
fits" was interpreted as only applying to update modes, despite the
words "or for writing only" appearing.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit d2e061a2bd3f7674cfef2e2217e0695419041b5e wrongly added this
case based on a misreading of the standard text regarding null
termination in write/update modes. apparently, the condition "if it
fits" was interpreted as only applying to update modes, despite the
words "or for writing only" appearing.
</pre>
</div>
</content>
</entry>
<entry>
<title>fix failure to report write error (ENOSPC) on fmemopen streams</title>
<updated>2026-05-05T23:47:21+00:00</updated>
<author>
<name>Rich Felker</name>
<email>dalias@aerifal.cx</email>
</author>
<published>2026-05-05T23:47:21+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=9086784bf2d883b68dabf78a68164e3c71cff206'/>
<id>9086784bf2d883b68dabf78a68164e3c71cff206</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>printf: fix buffer overflow in floating point decimal formatting</title>
<updated>2025-09-19T22:35:19+00:00</updated>
<author>
<name>Rich Felker</name>
<email>dalias@aerifal.cx</email>
</author>
<published>2025-09-19T22:35:19+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=0ccaf0572e9cccda2cced0f7ee659af4c1c6679a'/>
<id>0ccaf0572e9cccda2cced0f7ee659af4c1c6679a</id>
<content type='text'>
commit f96e47a26102d537c29435f0abf9ec94676a030e introduced a new
overflow past the end of the base-1e9 buffer for floating point to
decimal conversion while fixing a different overflow below the start
of the buffer.

this bug has not been present in any release, and has not been
analyzed in depth for security considerations.

the root cause of the bug, incorrect size accounting for the mantissa,
long predates the above commit, but was only exposed once the
excessive offset causing overflow in the other direction was removed.

the number of slots for expanding the mantissa was computed as if each
slot could peel off at least 29 bits. this would be true if the
mantissa were placed and expanded to the left of the radix point, but
we don't do that because it would require repeated fmod and division.
instead, we start the mantissa with 29 bits to the left of the radix
point, so that they can be peeled off by conversion to integer and
subtraction, followed by a multiplication by 1e9 to prepare for the
next iteration. so while the first slot peels 29 bits, advancing to
the next slot adds back somewhere between 20 and 21 bits: the length
of the mantissa of 1e9. this means we need to account for a slot for
every 8 bits of mantissa past the initial 29.

add a comment to that effect and adjust the max_mant_slots formula.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit f96e47a26102d537c29435f0abf9ec94676a030e introduced a new
overflow past the end of the base-1e9 buffer for floating point to
decimal conversion while fixing a different overflow below the start
of the buffer.

this bug has not been present in any release, and has not been
analyzed in depth for security considerations.

the root cause of the bug, incorrect size accounting for the mantissa,
long predates the above commit, but was only exposed once the
excessive offset causing overflow in the other direction was removed.

the number of slots for expanding the mantissa was computed as if each
slot could peel off at least 29 bits. this would be true if the
mantissa were placed and expanded to the left of the radix point, but
we don't do that because it would require repeated fmod and division.
instead, we start the mantissa with 29 bits to the left of the radix
point, so that they can be peeled off by conversion to integer and
subtraction, followed by a multiplication by 1e9 to prepare for the
next iteration. so while the first slot peels 29 bits, advancing to
the next slot adds back somewhere between 20 and 21 bits: the length
of the mantissa of 1e9. this means we need to account for a slot for
every 8 bits of mantissa past the initial 29.

add a comment to that effect and adjust the max_mant_slots formula.
</pre>
</div>
</content>
</entry>
<entry>
<title>printf: fix regression in large double formatting on ld128 archs</title>
<updated>2025-07-02T01:30:18+00:00</updated>
<author>
<name>Rich Felker</name>
<email>dalias@aerifal.cx</email>
</author>
<published>2025-07-02T01:30:18+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=f96e47a26102d537c29435f0abf9ec94676a030e'/>
<id>f96e47a26102d537c29435f0abf9ec94676a030e</id>
<content type='text'>
commit 572a2e2eb91f00f2f25d301cfb50f435e7ae16b3 adjusted the buffer
for decimal conversion to be a VLA that only uses the full size needed
for long double when the argument type was long double. however, it
failed to update a later expression for the positioning within the
buffer, which still used a fixed offset of LDBL_MANT_DIG. this caused
doubles with a large positive exponent to overflow below the start of
the array, producing wrong output and potentially runaway wrong
execution.

this bug has not been present in any release, and has not been
analyzed in depth for security considerations.

it turns out the original buffer offset expression involving
LDBL_MANT_DIG was incorrect as well, and only worked because the space
reserved for expanding the exponent is roughly 3 times the size it
needs to be when the exponent is positive, leaving plenty of extra
space to compensate for the error. the actual offset should be in
base-1000000000 slot units, not bits, and numerically equal to the
number of slots that were previously allocated for mantissa expansion.

in order to ensure consistency and make the code more comprehensible,
commented subexpressions are replaced by intermediate named variables,
and the newly introduced max_mant_slots is used for both the
allocation and the buffer offset adjustment. the included +1 term
accounts for a trailing zero slot that's always emitted.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit 572a2e2eb91f00f2f25d301cfb50f435e7ae16b3 adjusted the buffer
for decimal conversion to be a VLA that only uses the full size needed
for long double when the argument type was long double. however, it
failed to update a later expression for the positioning within the
buffer, which still used a fixed offset of LDBL_MANT_DIG. this caused
doubles with a large positive exponent to overflow below the start of
the array, producing wrong output and potentially runaway wrong
execution.

this bug has not been present in any release, and has not been
analyzed in depth for security considerations.

it turns out the original buffer offset expression involving
LDBL_MANT_DIG was incorrect as well, and only worked because the space
reserved for expanding the exponent is roughly 3 times the size it
needs to be when the exponent is positive, leaving plenty of extra
space to compensate for the error. the actual offset should be in
base-1000000000 slot units, not bits, and numerically equal to the
number of slots that were previously allocated for mantissa expansion.

in order to ensure consistency and make the code more comprehensible,
commented subexpressions are replaced by intermediate named variables,
and the newly introduced max_mant_slots is used for both the
allocation and the buffer offset adjustment. the included +1 term
accounts for a trailing zero slot that's always emitted.
</pre>
</div>
</content>
</entry>
<entry>
<title>stdio: skip empty iovec when buffering is disabled</title>
<updated>2025-05-27T14:06:37+00:00</updated>
<author>
<name>Casey Connolly</name>
<email>kcxt@postmarketos.org</email>
</author>
<published>2025-04-23T13:06:48+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=fde29c04adbab9d5b081bf6717b5458188647f1c'/>
<id>fde29c04adbab9d5b081bf6717b5458188647f1c</id>
<content type='text'>
When buffering on a FILE is disabled we still send both iovecs, even
though the first one is always empty. Clean things up by skipping the
empty iovec instead.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When buffering on a FILE is disabled we still send both iovecs, even
though the first one is always empty. Clean things up by skipping the
empty iovec instead.
</pre>
</div>
</content>
</entry>
<entry>
<title>printf: drastically reduce stack usage without [long] double args</title>
<updated>2024-08-26T20:01:11+00:00</updated>
<author>
<name>Rich Felker</name>
<email>dalias@aerifal.cx</email>
</author>
<published>2024-08-26T20:01:11+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=572a2e2eb91f00f2f25d301cfb50f435e7ae16b3'/>
<id>572a2e2eb91f00f2f25d301cfb50f435e7ae16b3</id>
<content type='text'>
internally, printf always works with the maximal-size supported
integer and floating point formats. however, the space needed to
format a floating point number is proportional to the mantissa and
exponent ranges. on archs where long double is larger than double,
knowing that the actual value fit in double allows us to use a much
smaller buffer, roughly 1/16 the size.

as a bonus, making the working buffer a VLA whose dimension depends on
the format specifier prevents the compiler from lifting the stack
adjustment to the top of printf_core. this makes it so printf calls
without floating point arguments do not waste even the smaller amount
of stack space needed for double, making it much more practical to use
printf in tightly stack-constrained environments.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
internally, printf always works with the maximal-size supported
integer and floating point formats. however, the space needed to
format a floating point number is proportional to the mantissa and
exponent ranges. on archs where long double is larger than double,
knowing that the actual value fit in double allows us to use a much
smaller buffer, roughly 1/16 the size.

as a bonus, making the working buffer a VLA whose dimension depends on
the format specifier prevents the compiler from lifting the stack
adjustment to the top of printf_core. this makes it so printf calls
without floating point arguments do not waste even the smaller amount
of stack space needed for double, making it much more practical to use
printf in tightly stack-constrained environments.
</pre>
</div>
</content>
</entry>
</feed>
