8082 Commits

Author SHA1 Message Date
Victor Zverovich
41f2838233 Remove test-only code from the headers and move equal2 to format-inl.h
Its only user is vformat_to, which needs only the char overload.
2026-11-08 06:37:50 -08:00
Ivan Lazarić
32777676cf
Fixup range formatting to match stdlib (#5005)
* Fixup range formatting to match stdlib

fmt would format a range of characters with `{:s}`
spec with surrounding quotes, whereas stdlib omits the quotes.
This patch drops the quotes.

* update docs
2026-11-08 06:33:02 -08:00
Shawn
9c19ea4664
Fix precision formatting of long double values just below a power of 10 (#5010)
* Fix precision formatting of long double values just below a power of 10

format_dragon included the upper boundary when checking whether the
estimated exponent is one too high. This is needed for the shortest
output, but with a given precision it left a leading zero digit, so
values such as nextafter(1e43L, 0) were printed with an extra digit in
fixed notation or a mantissa below 1 in exponent notation.

* Apply clang-format
2026-11-07 19:25:38 -08:00
Victor Zverovich
d102a01edf Truncate "(null)" to the precision and print null pointers as 0x0
Printing nothing for a small precision hides the null, and other libc
implementations truncate too. 0x0 matches fmt::format and std::format.
2026-11-07 19:04:02 -08:00
Victor Zverovich
1b5222af1b Clarify ostream capacity comment and strengthen zero buffer test
The old test only caught the overflow under ASan.
2026-11-07 16:51:20 -08:00
Victor Zverovich
a9e41a6df2 Rename rep to abs_rep in duration_formatter and simplify the tests
The old name differed from Rep only in case, which made the narrowing
fixed in #5003 easy to miss.
2026-11-07 15:42:47 -08:00
aizu-m
3a52eb4f1d
fix null pointer arithmetic for %s with precision in vprintf (#5001)
* fix null pointer arithmetic for %s with precision in vprintf

* Match glibc for null %s with a precision
2026-11-07 14:41:17 -08:00
Victor Zverovich
d93446e3dd Fix shifting the fallback uint128 by zero
A shift of 0 evaluated lo_ >> 64 or hi_ << 64, which is undefined.
2026-11-07 13:44:54 -08:00
Victor Zverovich
b2b9b074d4 Simplify hexfloat rounding and test long double ties
Avoids shifting by zero, which is undefined for the fallback uint128.
The float tie test duplicated the double one; floats format as doubles.
2026-11-07 12:58:14 -08:00
Victor Zverovich
dcdef1b80e Avoid 128-bit division when formatting 128-bit integers
Division by 10^19 compiled to a slow __udivti3 call. A reciprocal, as
suggested in #5006, makes 128-bit formatting ~1.8x faster on arm64.
2026-11-07 11:27:35 -08:00
Victor Zverovich
24ab1de71c Document why the SLSA generator is referenced by tag
Scorecard flags the tag as an unpinned dependency, but the generator
doesn't support being pinned by hash.
2026-11-07 09:34:40 -08:00
Victor Zverovich
31a44d5a83 Bump version 2026-11-07 09:34:40 -08:00
Victor Zverovich
cfa163aea8 Update changelog 2026-11-07 09:34:40 -08:00
aizu-m
4daaa87b86
fix heap overflow in fmt::ostream with buffer_size = 0 (#5011)
output_file(path, buffer_size = 0) allocated a zero-size buffer, but
ostream::grow can only make room by flushing, so a zero capacity is never
increased. push_back then writes past the allocation and leaves size()
above capacity(), after which append computes capacity_ - size_ as
SIZE_MAX and copies the rest of the output out of bounds. If the first
write is an append instead, the count is clamped to 0 and print never
returns.

Allocate at least one byte so a zero buffer size behaves like 1.
2026-11-07 09:14:57 -08:00
Victor Zverovich
73b747233e Ignore __pycache__
This also keeps it out of the source package.
2026-11-07 08:53:07 -08:00
Victor Zverovich
5750f9d0f4 Reuse size_padding for localized integers and simplify the test
Both integer writers now compute zero padding the same way.
2026-11-07 07:55:27 -08:00
Victor Zverovich
080b1d0219 Avoid a path string copy and move wide path tests to xchar-test
FMT_STATIC_THOUSANDS_SEPARATOR has had no effect since 11.1.0, so drop
its guard.
2026-11-07 07:27:07 -08:00
khan
47fcd357ab
Avoid narrowing duration day counts to the original representation (#5003)
* Avoid narrowing duration day counts to the original representation

* Keep duration field values in the promoted representation

---------

Co-authored-by: Aikhan Jumashukurov <117706338+aikhanj@users.noreply.github.com>
2026-11-06 15:44:43 -08:00
Eminy
9e7aaa3f27
Round hexfloat ties to even like printf (#5002) 2026-11-06 12:52:29 -08:00
Victor Zverovich
b1397ab7bc Fix valueless variant output and simplify literals in std.h
The catch block dropped the iterator returned by write, so the text
was lost when formatting into a pointer with FMT_COMPILE.
2026-11-06 11:35:06 -08:00
Ngo Quoc Viet
6864349b74
Fix generic path format when formatting to wide strings (#4999)
* Fix generic path format when formatting to wide strings

get_path_string used the native or generic string computed by the path
formatter only when converting wchar_t to UTF-8 and fell back to
p.string<Char>() otherwise, so the 'g' specifier was ignored when the
output character type matched path::value_type. On Windows,
fmt::format(L"{:g}", path(L"C:\\foo")) returned L"C:\\foo" instead of
L"C:/foo". Use the passed string in that case, as write_escaped_path
already does.

* Keep generic path format when converting to wide strings on POSIX
2026-11-06 10:08:34 -08:00
Marvel Harisson
7f7a16a131
Fix wide formatting of variant, monostate and expected (#4991)
The formatters for std::variant, std::monostate, std::expected and
std::unexpected wrote narrow string literals with detail::write<Char>,
which is ambiguous for wchar_t, so formatting these types into a wide
string failed to compile even though is_formattable reported them as
formattable. Use detail::string_literal like the std::optional
formatter does.
2026-11-06 09:57:48 -08:00
Victor Zverovich
7690aa5574 Simplify float to integral duration_cast and its tests
Compute the upper bound as 2^digits with std::ldexp instead of
static_cast<FromRep>(max) + 1, which is only exact when rounding to
nearest: with FE_UPWARD in an unoptimized build the bound became
2^63 + 2048 and a count of 2^63 reached the undefined conversion.
Truncate the count once and use it for both the check and the cast.

Skip the checks that need safe duration casts when
FMT_SAFE_DURATION_CAST is 0, where the NaN time point check failed.
Drop the 1e300 time point and two bool assertions, which don't catch
anything the others don't, and test max + 1 and NaN directly.
2026-11-06 09:43:42 -08:00
aizu-m
4ed3535092
Fix unchecked float to integral conversion in detail::duration_cast (#4985)
* fix unchecked float to integral conversion in detail::duration_cast

* Check the truncated count in float to integral duration_cast

* Keep the duration_cast fallback for custom representations

* Use an explicit rep in the custom_rep duration_cast test

std::chrono::seconds is duration<long> on 64-bit Linux so common_type<long,
custom_rep> had no specialization and chrono-test failed to compile there.

* Exclude bool from the checked float to integral duration_cast
2026-11-01 09:10:37 -08:00
dependabot[bot]
3ce0db1511
Bump ossf/scorecard-action from 2.4.2 to 2.5.0 (#5008)
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.2 to 2.5.0.
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](05b42c6244...fa7117db83)

---
updated-dependencies:
- dependency-name: ossf/scorecard-action
  dependency-version: 2.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-11-01 07:52:04 -08:00
Nathan Chandrasekar
09a606d17a
Fix zero padding for localized integers (#4994) 2026-10-31 10:15:44 -07:00
Victor Zverovich
dc4675a400 Simplify floating-point 12-hour test 2026-10-31 08:38:20 -07:00
Nathan Chandrasekar
92d2c541e3
Fix 12-hour formatting of floating-point durations (#4988) 2026-10-31 08:27:00 -07:00
Victor Zverovich
8362a1be15 Reduce code size of hexfloat formatting
Move writing of the formatted hexfloat into write_hexfloat, which only
depends on the character and iterator types, so that it is not duplicated
for each floating-point type, and mark decimal_point_impl noinline to
avoid inlining the std::locale lookup into every caller.
2026-10-30 13:03:19 -07:00
Victor Zverovich
97bd2ad530 Simplify ISO week computation
Compute the ISO week-based year and week number from the day of the year
of the Thursday in the current week instead of the weekday of December 31.
This only needs a leap year check, which works for negative years without
floored division, and is about 3 times faster.

For std::tm values with tm_wday and tm_yday inconsistent with tm_year,
%G, %g and %V now give the same results as strftime.

Replace the negative year tests with a year_month_day test that also
covers the leap year check and days_from_civil for negative years.
2026-10-30 11:53:17 -07:00
Victor Zverovich
f87a75e152 Clean up duration_formatter and simplify duration sign tests 2026-10-25 09:34:12 -07:00
Marvel Harisson
2e60743c67
Fix formatting of nullptr with FMT_COMPILE and to_string (#4993)
* Fix formatting of nullptr with FMT_COMPILE and to_string

std::nullptr_t is implicitly convertible to string_view and const char*,
so compiled format strings and fmt::to_string treated nullptr as a null
C string: FMT_COMPILE("{}!") crashed and FMT_COMPILE("{}") and to_string
threw "string pointer is null". Format it as a pointer ("0x0") like the
runtime API does.

* Write nullptr as a pointer in detail::write

detail::write<Char>(out, nullptr) picked the const Char* overload, so
fmt::to_string(nullptr) and FMT_COMPILE("{}") threw "string pointer is
null". Add a nullptr_t overload that forwards to the const void* one.
2026-10-25 09:30:45 -07:00
aizu-m
3a2dcb59ef
Don't truncate output size to int in fmt_vformat and vfprintf (#4987)
* Don't truncate output size to int in fmt_vformat and vfprintf

* Check size before writing in vfprintf
2026-10-25 09:17:26 -07:00
Marvel Harisson
88a0ae2020
Use the locale decimal point in localized hexfloat formatting (#4992)
With the L flag, floating-point values are formatted with the locale's
decimal point, but the hexfloat presentation ('a'/'A') always emitted
'.'. Replace it with the locale decimal point when the value is
localized, like the other floating-point presentations do.
2026-10-24 11:15:30 -07:00
Mohith
434e30f81f
Fix signs in floating-point duration formatting (#4981) 2026-10-24 10:28:23 -07:00
Victor Zverovich
a8293b774e Bump certifi to 2026.10.23 2026-10-24 10:17:28 -07:00
Victor Zverovich
6b528261ec Fix allocation size overflow in detail::allocator
allocator<T>::allocate(n) computed n * sizeof(T) with only an FMT_ASSERT
guarding against overflow, which is a no-op under NDEBUG. On 32-bit targets
a width of 2^30 or more with a 4-byte character type, e.g.
fmt::format(L"{:>{}}", s, 1100000000), wraps the byte count around, and
basic_memory_buffer records a capacity much larger than the block it got,
so padding is written past the end of the allocation.

Make the check unconditional and throw std::bad_alloc, as std::allocator
did before it was replaced in 11.1.0. Move <new> back to format.h since the
header now throws std::bad_alloc.
2026-10-24 10:03:53 -07:00
DeviousCardi
011e5a911f
Fix ISO week number and year for negative years (#4989)
iso_year_weeks computed the weekday of December 31 with truncating
division and a remainder that is negative for negative years, so it
returned the wrong number of ISO weeks for years before year 0. As a
result %V and %G/%g were wrong around the start and end of such years,
e.g. 1 January of year -1 was formatted as week 52 of year -2 instead
of week 53, and 31 December of year -2 as week 1 of year -1.

Use floored division and a non-negative remainder.


Claude-Session: https://claude.ai/code/session_01Y1b55sEL1gA1c3FCMcQCbm

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-24 09:59:35 -07:00
fhgffy
0fc31633e7
Fix weekday and day of year when formatting year_month_day (#4978)
The year_month_day formatter only filled in tm_year, tm_mon and tm_mday,
so specifiers that depend on the weekday or the day of the year (%a, %A,
%u, %w, %j, %U, %W, %V, %G, %g) were formatted from zero-initialized
fields, e.g. every date was printed as a Sunday. Compute tm_wday and
tm_yday from the date before passing it to the tm formatter.
2026-10-18 07:14:35 -07:00
Mayank Jaiswal
89a7f4a7ca
Fix FMT_COMPILE with ranges, tuples and maps (#4974)
nested_format_specs::write formatted the body of a padded value into a
temporary buffer using a context of the same type as the outer one. This
only works when the outer context writes to an appender, so FMT_COMPILE
and format_to with other output iterators failed to compile even when no
width was given.

Use a buffer context that takes arguments and locale from the outer
context when the outer context doesn't write to an appender.

Fixes #4949.
2026-10-18 07:11:07 -07:00
Victor Zverovich
4ded41f186 Simplify pre-epoch local_time formatting
Floor the seconds before calling gmtime instead of adjusting tm_sec, and
keep the subsecond remainder in the common duration type, which fixes
overflow for narrow reps such as duration<int16_t, std::micro>.
2026-10-18 07:02:27 -07:00
Kartikey Negi
6ba294f5a6
Fix subsecond formatting for pre-epoch local_time (#4975) (#4976) 2026-10-18 06:45:15 -07:00
Victor Zverovich
18164eaf8b Simplify printf flag tests
The sign is cleared for unsigned conversions regardless of whether the
'+' or the space flag was given, so "% o" and "% X" only repeat what
"%+o" and "%+X" already cover.
2026-10-17 07:16:33 -07:00
fhgffy
01bef95d34
Ignore '+' and space flags for unsigned printf conversions (#4977)
C only applies the '+' and space flags to signed conversions, so
fmt::sprintf("%+u", 42) should give "42" like printf does, not "+42".
The same goes for %o, %x and %X.
2026-10-17 07:11:43 -07:00
Victor Zverovich
8efd79f3f0 Simplify hexfloat formatting
For numeric alignment write the 0x prefix directly to the output and
subtract it from the width instead of tracking the prefix length
separately. This makes the extra write_padded call and the intermediate
buffer copy unnecessary, restoring write_bytes.
2026-10-17 06:42:21 -07:00
Victor Zverovich
fdf31252e6 Cache packages in Linux CI
Compilers are installed from third-party archives that periodically
return 50x or throttle to a crawl, which fails the build. Keep the
downloaded packages and restore them on the next run so that both apt
and the legacy wget-based installs work from disk instead of refetching.

apt, unlike apt-get, discards downloaded packages after installing them
unless the binary-specific Keep-Downloaded-Packages is set.

The cache is written once per key; bump the -v1 suffix to refresh it
after the package versions change.
2026-10-16 16:02:06 -07:00
Victor Zverovich
7a3b442edc Simplify sanitizer flags in Linux CI workflow
Inline the SANITIZER_FLAGS expression into CXXFLAGS and drop CFLAGS.
c-test is the only C target and CMake links it with the C++ driver because
it depends on fmt-c, so the sanitizer runtime is still linked in.
2026-10-16 12:44:14 -07:00
Victor Zverovich
615acd84dd Fix use-after-free in basic_memory_buffer move assignment
operator= deallocates the destination's storage but leaves it pointing at
the freed block with a stale capacity and size. When the allocator doesn't
propagate and the two allocators are unequal, move_alloc copies into that
pointer rather than taking over the source's storage, so it writes to freed
memory and the destructor then frees the same block again.

Restore the inline buffer after deallocating and before calling move().
2026-10-16 12:44:14 -07:00
Ivan Lazarić
b4ffa39b99
Block optimize pragma on EDG (#4980)
EDG over GCC likes to pretend to be GCC in a lot of macros,
but not all. It does not define `__OPTIMIZE__` ever.
So we would erroneously emit pragma optimize `Og`
even in optimized builds.
2026-10-11 15:29:11 -07:00
Vladislav Shchapov
35c58f084e
Fix hexfloat zero padding: zero padding must be placed after the sign and "0x" prefix (#4972)
Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru>
2026-10-08 13:06:28 -07:00