Skip to content

Commit d4d2b0c

Browse files
dvyukovvitalybuka
authored andcommitted
sanitizer_common: support %l in format strings
Currently we only support %z and %ll width modifiers, but surprisingly not %l. This makes it impossible to print longs (sizeof(long) not necessary equal to sizeof(size_t)). We had some printf's that printed longs with %zu, but that's wrong and now with __attribute__((format)) in place they are flagged by compiler. So we either have a choice of doing static_cast<uptr>(long) everywhere or add %l. Adding %l looks better, that's a standard modifier. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D108066
1 parent f1de9d6 commit d4d2b0c

File tree

2 files changed

+10
-3
lines changed

2 files changed

+10
-3
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_printf.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
128128
int VSNPrintf(char *buff, int buff_length,
129129
const char *format, va_list args) {
130130
static const char *kPrintfFormatsHelp =
131-
"Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; "
131+
"Supported Printf formats: %([0-9]*)?(z|l|ll)?{d,u,x,X}; %p; "
132132
"%[-]([0-9]*)?(\\.\\*)?s; %c\n";
133133
RAW_CHECK(format);
134134
RAW_CHECK(buff_length > 0);
@@ -160,16 +160,19 @@ int VSNPrintf(char *buff, int buff_length,
160160
}
161161
bool have_z = (*cur == 'z');
162162
cur += have_z;
163-
bool have_ll = !have_z && (cur[0] == 'l' && cur[1] == 'l');
163+
bool have_l = cur[0] == 'l' && cur[1] != 'l';
164+
cur += have_l;
165+
bool have_ll = cur[0] == 'l' && cur[1] == 'l';
164166
cur += have_ll * 2;
165-
const bool have_length = have_z || have_ll;
167+
const bool have_length = have_z || have_l || have_ll;
166168
const bool have_flags = have_width || have_length;
167169
// At the moment only %s supports precision and left-justification.
168170
CHECK(!((precision >= 0 || left_justified) && *cur != 's'));
169171
switch (*cur) {
170172
case 'd': {
171173
s64 dval = have_ll ? va_arg(args, s64)
172174
: have_z ? va_arg(args, sptr)
175+
: have_l ? va_arg(args, long)
173176
: va_arg(args, int);
174177
result += AppendSignedDecimal(&buff, buff_end, dval, width,
175178
pad_with_zero);
@@ -180,6 +183,7 @@ int VSNPrintf(char *buff, int buff_length,
180183
case 'X': {
181184
u64 uval = have_ll ? va_arg(args, u64)
182185
: have_z ? va_arg(args, uptr)
186+
: have_l ? va_arg(args, unsigned long)
183187
: va_arg(args, unsigned);
184188
bool uppercase = (*cur == 'X');
185189
result += AppendUnsigned(&buff, buff_end, uval, (*cur == 'u') ? 10 : 16,

compiler-rt/lib/sanitizer_common/tests/sanitizer_printf_test.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ TEST(Printf, MinMax) {
115115
TestAgainstLibc<int>("%d-%d", INT_MIN, INT_MAX);
116116
TestAgainstLibc<unsigned>("%u-%u", 0, UINT_MAX);
117117
TestAgainstLibc<unsigned>("%x-%x", 0, UINT_MAX);
118+
TestAgainstLibc<long>("%ld-%ld", LONG_MIN, LONG_MAX);
119+
TestAgainstLibc<unsigned long>("%lu-%lu", 0, LONG_MAX);
120+
TestAgainstLibc<unsigned long>("%lx-%lx", 0, LONG_MAX);
118121
#if !defined(_WIN32)
119122
// %z* format doesn't seem to be supported by MSVS.
120123
TestAgainstLibc<long>("%zd-%zd", LONG_MIN, LONG_MAX);

0 commit comments

Comments
 (0)