<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>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>
<entry>
<title>printf core: replace if(0) blocks around switch cases with explicit gotos</title>
<updated>2024-08-18T17:53:39+00:00</updated>
<author>
<name>Rich Felker</name>
<email>dalias@aerifal.cx</email>
</author>
<published>2024-08-18T17:53:39+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=ee18e584bfe2c694fdd27bd1251ac5b247f864d5'/>
<id>ee18e584bfe2c694fdd27bd1251ac5b247f864d5</id>
<content type='text'>
this is purely a readability change, not a functional one. all of the
integer format cases use a common tail for handling precision logic
after the string representation of the number has been generated. the
code as I originally wrote it was overly clever in the aim of making a
point that the flow could be done without goto, and jumped over
intervening cases by wrapping them in if (0) { }, with the case labels
for each inside the conditional block scope.

this has been a perpetual source of complaints about the readability
and comprehensibility of the file, so I am now changing it to
explicitly jump to the tail logic with goto statements.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
this is purely a readability change, not a functional one. all of the
integer format cases use a common tail for handling precision logic
after the string representation of the number has been generated. the
code as I originally wrote it was overly clever in the aim of making a
point that the flow could be done without goto, and jumped over
intervening cases by wrapping them in if (0) { }, with the case labels
for each inside the conditional block scope.

this has been a perpetual source of complaints about the readability
and comprehensibility of the file, so I am now changing it to
explicitly jump to the tail logic with goto statements.
</pre>
</div>
</content>
</entry>
<entry>
<title>printf decimal integer formatting: shave off one division</title>
<updated>2024-05-06T21:13:23+00:00</updated>
<author>
<name>Rich Felker</name>
<email>dalias@aerifal.cx</email>
</author>
<published>2024-05-06T21:13:23+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=3f9d4224d8db7868b6c2f526746d597785d30c61'/>
<id>3f9d4224d8db7868b6c2f526746d597785d30c61</id>
<content type='text'>
once the remaining value is less than 10, the modulo operation to
produce the final digit and division to prepare for next loop
iteration can be dropped. this may be a meaningful performance
distinction when formatting low-magnitude numbers in bulk, and should
never hurt.

based on patch by Viktor Reznov.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
once the remaining value is less than 10, the modulo operation to
produce the final digit and division to prepare for next loop
iteration can be dropped. this may be a meaningful performance
distinction when formatting low-magnitude numbers in bulk, and should
never hurt.

based on patch by Viktor Reznov.
</pre>
</div>
</content>
</entry>
<entry>
<title>printf: fix edge case where hex float precision was not honored</title>
<updated>2024-04-12T23:57:59+00:00</updated>
<author>
<name>Rich Felker</name>
<email>dalias@aerifal.cx</email>
</author>
<published>2024-04-12T23:57:59+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=24ebbbdedcf626808a902d8797df239f94af9620'/>
<id>24ebbbdedcf626808a902d8797df239f94af9620</id>
<content type='text'>
commit cfa0a54c082d41db6446638eed1d57f163434092 attempted to fix
rounding on archs where long double is not 80-bit (where LDBL_MANT_DIG
is not zero mod four), but failed to address the edge case where
rounding was skipped because LDBL_MANT_DIG/4 rounded down in the
comparison against the requested precision.

the rounding logic based on hex digit count is difficult to understand
and not well-motivated, so rather than try to fix it, replace it with
an explicit calculation in terms of number of bits to be kept, without
any truncating division operations. based on patch by Peter Ammon, but
with scalbn to apply the rounding exponent since the value will not
generally fit in any integer type. scalbn is used instead of scalbnl
to avoid pulling in the latter unnecessarily, since the value is an
exact power of two whose exponent range is bounded by LDBL_MANT_DIG, a
small integer.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit cfa0a54c082d41db6446638eed1d57f163434092 attempted to fix
rounding on archs where long double is not 80-bit (where LDBL_MANT_DIG
is not zero mod four), but failed to address the edge case where
rounding was skipped because LDBL_MANT_DIG/4 rounded down in the
comparison against the requested precision.

the rounding logic based on hex digit count is difficult to understand
and not well-motivated, so rather than try to fix it, replace it with
an explicit calculation in terms of number of bits to be kept, without
any truncating division operations. based on patch by Peter Ammon, but
with scalbn to apply the rounding exponent since the value will not
generally fit in any integer type. scalbn is used instead of scalbnl
to avoid pulling in the latter unnecessarily, since the value is an
exact power of two whose exponent range is bounded by LDBL_MANT_DIG, a
small integer.
</pre>
</div>
</content>
</entry>
<entry>
<title>add framework to support archs without a native wait4 syscall</title>
<updated>2024-02-22T23:50:34+00:00</updated>
<author>
<name>Rich Felker</name>
<email>dalias@aerifal.cx</email>
</author>
<published>2024-02-22T23:50:34+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=19563e1850808af216b1b84263bb7e83cccce506'/>
<id>19563e1850808af216b1b84263bb7e83cccce506</id>
<content type='text'>
this commit should make no codegen change for existing archs, but is a
prerequisite for new archs including riscv32. the wait4 emulation
backend provides both cancellable and non-cancellable variants because
waitpid is required to be a cancellation point, but all of our other
uses are not, and most of them cannot be.

based on patch by Stefan O'Rear.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
this commit should make no codegen change for existing archs, but is a
prerequisite for new archs including riscv32. the wait4 emulation
backend provides both cancellable and non-cancellable variants because
waitpid is required to be a cancellation point, but all of our other
uses are not, and most of them cannot be.

based on patch by Stefan O'Rear.
</pre>
</div>
</content>
</entry>
<entry>
<title>remove INT_MAX limit on the n argument to snprintf/swprintf</title>
<updated>2024-01-17T23:11:58+00:00</updated>
<author>
<name>Rich Felker</name>
<email>dalias@aerifal.cx</email>
</author>
<published>2024-01-17T23:11:58+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=11fb383275d20f5f94c00425bd888a02ecbd218e'/>
<id>11fb383275d20f5f94c00425bd888a02ecbd218e</id>
<content type='text'>
this was a POSIX requirement that was always in conflict with ISO C,
which specified a well-defined behavior for snprintf and swprintf so
long as the actual number of bytes/characters produced did not exceed
INT_MAX.

I originally raised this conflict for snprintf with the Austin Group
as tracker issue 761, which was never resolved. it was later reported
again as issue 1219, and as a result the conflicting requirement has
been removed.

the corresponding issue with swprintf does not seem to have been
addressed, but as the same reasoning applies to it, I am removing the
limitation on n for swprintf as well.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
this was a POSIX requirement that was always in conflict with ISO C,
which specified a well-defined behavior for snprintf and swprintf so
long as the actual number of bytes/characters produced did not exceed
INT_MAX.

I originally raised this conflict for snprintf with the Austin Group
as tracker issue 761, which was never resolved. it was later reported
again as issue 1219, and as a result the conflicting requirement has
been removed.

the corresponding issue with swprintf does not seem to have been
addressed, but as the same reasoning applies to it, I am removing the
limitation on n for swprintf as well.
</pre>
</div>
</content>
</entry>
<entry>
<title>byte-based printf family: emit a nul byte for %lc with argument zero</title>
<updated>2023-11-06T18:59:06+00:00</updated>
<author>
<name>Rich Felker</name>
<email>dalias@aerifal.cx</email>
</author>
<published>2023-11-06T18:59:06+00:00</published>
<link rel='alternate' type='text/html' href='http://git.musl-libc.org/cgit/musl/commit/?id=7b6a6516e133a4154022de4d15b3d5bc800ab3ad'/>
<id>7b6a6516e133a4154022de4d15b3d5bc800ab3ad</id>
<content type='text'>
this is contrary to the spec as written, which requires %lc to behave
as if it were %ls on a 2-wchar_t buffer containing the argument and
zero. however, apparently no other implementations conform to the spec
as written, and in response to Austin Group issue #1647, WG14 chose to
align with existing practice and have %lc produce output for this case.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
this is contrary to the spec as written, which requires %lc to behave
as if it were %ls on a 2-wchar_t buffer containing the argument and
zero. however, apparently no other implementations conform to the spec
as written, and in response to Austin Group issue #1647, WG14 chose to
align with existing practice and have %lc produce output for this case.
</pre>
</div>
</content>
</entry>
</feed>
