Skip to content

Commit 300ce75

Browse files
committed
Handle invalid glibc FILE buffer
1 parent 513f978 commit 300ce75

File tree

2 files changed

+16
-1
lines changed

2 files changed

+16
-1
lines changed

include/fmt/format-inl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1549,7 +1549,8 @@ template <typename F> class glibc_file : public file_base<F> {
15491549
bool needs_flush() const {
15501550
if ((this->file_->_flags & line_buffered) == 0) return false;
15511551
char* end = this->file_->_IO_write_end;
1552-
return memchr(end, '\n', to_unsigned(this->file_->_IO_write_ptr - end));
1552+
auto size = max_of<ptrdiff_t>(this->file_->_IO_write_ptr - end, 0);
1553+
return memchr(end, '\n', static_cast<size_t>(size));
15531554
}
15541555

15551556
void flush() { fflush_unlocked(this->file_); }

test/format-test.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2549,6 +2549,20 @@ TEST(format_test, writer) {
25492549
EXPECT_EQ(s.str(), "foo");
25502550
}
25512551

2552+
#if FMT_USE_FCNTL && !defined(_WIN32)
2553+
TEST(format_test, invalid_glibc_buffer) {
2554+
auto pipe = fmt::pipe();
2555+
auto write_end = pipe.write_end.fdopen("w");
2556+
auto file = write_end.get();
2557+
2558+
// This results in _IO_write_ptr < _IO_write_end.
2559+
fprintf(file, "111\n");
2560+
setvbuf(file, nullptr, _IOLBF, 0);
2561+
2562+
fmt::print(file, "------\n");
2563+
}
2564+
#endif // FMT_USE_FCNTL
2565+
25522566
#if FMT_USE_BITINT
25532567
FMT_PRAGMA_CLANG(diagnostic ignored "-Wbit-int-extension")
25542568

0 commit comments

Comments
 (0)