Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
url = https://github.com/ClickHouse/libuv
[submodule "contrib/fmtlib"]
path = contrib/fmtlib
url = https://github.com/fmtlib/fmt
url = https://github.com/ClickHouse/fmt
[submodule "contrib/krb5"]
path = contrib/krb5
url = https://github.com/ClickHouse/krb5
Expand Down
2 changes: 1 addition & 1 deletion contrib/fmtlib
32 changes: 32 additions & 0 deletions tests/queries/0_stateless/04094_printf_trailing_percent.reference
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
%
%
hello %
hello %
%val
%val
a%b%c
a%b%c
% 42
% 42
42 %
42 %
42 % hi
42 % hi
%%
%%
42
42
hello
hello
val=100 end
val=100 end
1 x 2
1 x 2
42
42
2a
52
hello
%
abc%def
%%
57 changes: 57 additions & 0 deletions tests/queries/0_stateless/04094_printf_trailing_percent.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
-- Test printf with trailing '%' and various %% escaping edge cases.
-- Covers both constant and dynamic (materialized) format paths.
-- Regression test for MSan read-past-end in fmt::sprintf with lone '%'.

-- Constant format: lone '%' with argument (treated as literal)
SELECT printf('%', 42); -- { serverError BAD_ARGUMENTS }
SELECT printf('%', 'hello'); -- { serverError BAD_ARGUMENTS }

-- Materialized format: lone '%' with argument
SELECT printf(materialize('%'), 42); -- { serverError BAD_ARGUMENTS }
SELECT printf(materialize('%'), 'hello'); -- { serverError BAD_ARGUMENTS }

-- Constant format: lone '%' without argument (error)
SELECT printf('%'); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }

-- Materialized format: lone '%' without argument (error)
SELECT printf(materialize('%')); -- { serverError BAD_ARGUMENTS }

-- Trailing '%' after literal text
SELECT printf('abc%', 42); -- { serverError BAD_ARGUMENTS }
SELECT printf(materialize('abc%'), 42); -- { serverError BAD_ARGUMENTS }

-- Double percent escaping
SELECT printf('%%');
SELECT printf(materialize('%%'));
SELECT printf('hello %%');
SELECT printf(materialize('hello %%'));
SELECT printf('%%val');
SELECT printf(materialize('%%val'));
SELECT printf('a%%b%%c');
SELECT printf(materialize('a%%b%%c'));

-- Double percent with arguments
SELECT printf('%% %d', 42);
SELECT printf(materialize('%% %d'), 42);
SELECT printf('%d %%', 42);
SELECT printf(materialize('%d %%'), 42);
SELECT printf('%d %% %s', 42, 'hi');
SELECT printf(materialize('%d %% %s'), 42, 'hi');

-- Multiple trailing percents
SELECT printf('%%%%');
SELECT printf(materialize('%%%%'));

-- Normal format specifiers (sanity check)
SELECT printf('%d', 42);
SELECT printf(materialize('%d'), 42);
SELECT printf('%s', 'hello');
SELECT printf(materialize('%s'), 'hello');
SELECT printf('val=%d end', 100);
SELECT printf(materialize('val=%d end'), 100);
SELECT printf('%d %s %d', 1, 'x', 2);
SELECT printf(materialize('%d %s %d'), 1, 'x', 2);

-- Dynamic format from column
SELECT printf(s, 42) FROM (SELECT arrayJoin(['%d', '%5d', '%x', '%o']) AS s);
SELECT printf(s) FROM (SELECT arrayJoin(['hello', '%%', 'abc%%def', '%%%%']) AS s);
Loading