Skip to content

Commit 9f10f34

Browse files
committedDec 15, 2016
Fix printf specifier handling: invalid specifier should not be marked as "consuming data arguments"
Reviewers: rsmith, bruno, dexonsmith Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D27796 llvm-svn: 289850
1 parent 9a038c1 commit 9f10f34

File tree

4 files changed

+35
-5
lines changed

4 files changed

+35
-5
lines changed
 

Diff for: ‎clang/include/clang/Analysis/Analyses/FormatString.h

+2
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ class ConversionSpecifier {
211211
return false;
212212
case PercentArg:
213213
return false;
214+
case InvalidSpecifier:
215+
return false;
214216
default:
215217
return true;
216218
}

Diff for: ‎clang/test/CodeGen/builtins.c

+28
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,34 @@ void test_builtin_os_log_precision_width(void *buf, const char *data,
538538
__builtin_os_log_format(buf, "Hello %*.*s World", precision, width, data);
539539
}
540540

541+
// CHECK-LABEL: define void @test_builtin_os_log_invalid
542+
// CHECK: (i8* [[BUF:%.*]], i32 [[DATA:%.*]])
543+
void test_builtin_os_log_invalid(void *buf, int data) {
544+
volatile int len;
545+
// CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8
546+
// CHECK: store i32 [[DATA]], i32* [[DATA_ADDR:%.*]]
547+
548+
// CHECK: store volatile i32 8,
549+
len = __builtin_os_log_format_buffer_size("invalid specifier %: %d even a trailing one%", data);
550+
551+
// CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]]
552+
// CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0
553+
// CHECK: store i8 0, i8* [[SUMMARY]]
554+
// CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1
555+
// CHECK: store i8 1, i8* [[NUM_ARGS]]
556+
557+
// CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2
558+
// CHECK: store i8 0, i8* [[ARG1_DESC]]
559+
// CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3
560+
// CHECK: store i8 4, i8* [[ARG1_SIZE]]
561+
// CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4
562+
// CHECK: [[ARG1_INT:%.*]] = bitcast i8* [[ARG1]] to i32*
563+
// CHECK: [[ARG1_VAL:%.*]] = load i32, i32* [[DATA_ADDR]]
564+
// CHECK: store i32 [[ARG1_VAL]], i32* [[ARG1_INT]]
565+
566+
__builtin_os_log_format(buf, "invalid specifier %: %d even a trailing one%", data);
567+
}
568+
541569
// CHECK-LABEL: define void @test_builtin_os_log_percent
542570
// CHECK: (i8* [[BUF:%.*]], i8* [[DATA1:%.*]], i8* [[DATA2:%.*]])
543571
// Check that the %% which does not consume any argument is correctly handled

Diff for: ‎clang/test/Sema/format-strings.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,10 @@ void check_writeback_specifier()
156156

157157
void check_invalid_specifier(FILE* fp, char *buf)
158158
{
159-
printf("%s%lb%d","unix",10,20); // expected-warning {{invalid conversion specifier 'b'}}
159+
printf("%s%lb%d","unix",10,20); // expected-warning {{invalid conversion specifier 'b'}} expected-warning {{data argument not used by format string}}
160160
fprintf(fp,"%%%l"); // expected-warning {{incomplete format specifier}}
161161
sprintf(buf,"%%%%%ld%d%d", 1, 2, 3); // expected-warning{{format specifies type 'long' but the argument has type 'int'}}
162-
snprintf(buf, 2, "%%%%%ld%;%d", 1, 2, 3); // expected-warning{{format specifies type 'long' but the argument has type 'int'}} expected-warning {{invalid conversion specifier ';'}}
162+
snprintf(buf, 2, "%%%%%ld%;%d", 1, 2, 3); // expected-warning{{format specifies type 'long' but the argument has type 'int'}} expected-warning {{invalid conversion specifier ';'}} expected-warning {{data argument not used by format string}}
163163
}
164164

165165
void check_null_char_string(char* b)
@@ -251,7 +251,7 @@ void test10(int x, float f, int i, long long lli) {
251251
printf("%**\n"); // expected-warning{{invalid conversion specifier '*'}}
252252
printf("%d%d\n", x); // expected-warning{{more '%' conversions than data arguments}}
253253
printf("%d\n", x, x); // expected-warning{{data argument not used by format string}}
254-
printf("%W%d\n", x, x); // expected-warning{{invalid conversion specifier 'W'}}
254+
printf("%W%d\n", x, x); // expected-warning{{invalid conversion specifier 'W'}} expected-warning {{data argument not used by format string}}
255255
printf("%"); // expected-warning{{incomplete format specifier}}
256256
printf("%.d", x); // no-warning
257257
printf("%.", x); // expected-warning{{incomplete format specifier}}
@@ -270,7 +270,7 @@ void test10(int x, float f, int i, long long lli) {
270270
printf("%.0Lf", (long double) 1.0); // no-warning
271271
printf("%c\n", "x"); // expected-warning{{format specifies type 'int' but the argument has type 'char *'}}
272272
printf("%c\n", 1.23); // expected-warning{{format specifies type 'int' but the argument has type 'double'}}
273-
printf("Format %d, is %! %f", 1, 2, 4.4); // expected-warning{{invalid conversion specifier '!'}}
273+
printf("Format %d, is %! %f", 1, 4.4); // expected-warning{{invalid conversion specifier '!'}}
274274
}
275275

276276
typedef unsigned char uint8_t;

Diff for: ‎clang/test/SemaObjC/format-strings-objc.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ @interface NSConstantString : NSSimpleCString @end
4747

4848
void check_nslog(unsigned k) {
4949
NSLog(@"%d%%", k); // no-warning
50-
NSLog(@"%s%lb%d", "unix", 10,20); // expected-warning {{invalid conversion specifier 'b'}}
50+
NSLog(@"%s%lb%d", "unix", 10, 20); // expected-warning {{invalid conversion specifier 'b'}} expected-warning {{data argument not used by format string}}
5151
}
5252

5353
// Check type validation

0 commit comments

Comments
 (0)
Please sign in to comment.