1*89a1d03eSRichard // RUN: %check_clang_tidy %s cert-err34-c %t -- -- -std=c11
2*89a1d03eSRichard
3*89a1d03eSRichard typedef __SIZE_TYPE__ size_t;
4*89a1d03eSRichard typedef signed ptrdiff_t;
5*89a1d03eSRichard typedef long long intmax_t;
6*89a1d03eSRichard typedef unsigned long long uintmax_t;
7*89a1d03eSRichard typedef void * FILE;
8*89a1d03eSRichard
9*89a1d03eSRichard extern FILE *stdin;
10*89a1d03eSRichard
11*89a1d03eSRichard extern int fscanf(FILE * restrict stream, const char * restrict format, ...);
12*89a1d03eSRichard extern int scanf(const char * restrict format, ...);
13*89a1d03eSRichard extern int sscanf(const char * restrict s, const char * restrict format, ...);
14*89a1d03eSRichard
15*89a1d03eSRichard extern double atof(const char *nptr);
16*89a1d03eSRichard extern int atoi(const char *nptr);
17*89a1d03eSRichard extern long int atol(const char *nptr);
18*89a1d03eSRichard extern long long int atoll(const char *nptr);
19*89a1d03eSRichard
f1(const char * in)20*89a1d03eSRichard void f1(const char *in) {
21*89a1d03eSRichard int i;
22*89a1d03eSRichard long long ll;
23*89a1d03eSRichard unsigned int ui;
24*89a1d03eSRichard unsigned long long ull;
25*89a1d03eSRichard intmax_t im;
26*89a1d03eSRichard uintmax_t uim;
27*89a1d03eSRichard float f;
28*89a1d03eSRichard double d;
29*89a1d03eSRichard long double ld;
30*89a1d03eSRichard
31*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
32*89a1d03eSRichard sscanf(in, "%d", &i);
33*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoll' instead [cert-err34-c]
34*89a1d03eSRichard fscanf(stdin, "%lld", &ll);
35*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to an unsigned integer value, but function will not report conversion errors; consider using 'strtoul' instead [cert-err34-c]
36*89a1d03eSRichard sscanf(in, "%u", &ui);
37*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to an unsigned integer value, but function will not report conversion errors; consider using 'strtoull' instead [cert-err34-c]
38*89a1d03eSRichard fscanf(stdin, "%llu", &ull);
39*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoimax' instead [cert-err34-c]
40*89a1d03eSRichard scanf("%jd", &im);
41*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to an unsigned integer value, but function will not report conversion errors; consider using 'strtoumax' instead [cert-err34-c]
42*89a1d03eSRichard fscanf(stdin, "%ju", &uim);
43*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtof' instead [cert-err34-c]
44*89a1d03eSRichard sscanf(in, "%f", &f); // to float
45*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'fscanf' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtod' instead [cert-err34-c]
46*89a1d03eSRichard fscanf(stdin, "%lg", &d);
47*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'sscanf' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtold' instead [cert-err34-c]
48*89a1d03eSRichard sscanf(in, "%Le", &ld);
49*89a1d03eSRichard
50*89a1d03eSRichard // These are conversions with other modifiers
51*89a1d03eSRichard short s;
52*89a1d03eSRichard char c;
53*89a1d03eSRichard size_t st;
54*89a1d03eSRichard ptrdiff_t pt;
55*89a1d03eSRichard
56*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
57*89a1d03eSRichard scanf("%hhd", &c);
58*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
59*89a1d03eSRichard scanf("%hd", &s);
60*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
61*89a1d03eSRichard scanf("%zu", &st);
62*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
63*89a1d03eSRichard scanf("%td", &pt);
64*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
65*89a1d03eSRichard scanf("%o", ui);
66*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
67*89a1d03eSRichard scanf("%X", ui);
68*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
69*89a1d03eSRichard scanf("%x", ui);
70*89a1d03eSRichard }
71*89a1d03eSRichard
f2(const char * in)72*89a1d03eSRichard void f2(const char *in) {
73*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:11: warning: 'atoi' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
74*89a1d03eSRichard int i = atoi(in); // to int
75*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:12: warning: 'atol' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead [cert-err34-c]
76*89a1d03eSRichard long l = atol(in); // to long
77*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:18: warning: 'atoll' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtoll' instead [cert-err34-c]
78*89a1d03eSRichard long long ll = atoll(in); // to long long
79*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:14: warning: 'atof' used to convert a string to a floating-point value, but function will not report conversion errors; consider using 'strtod' instead [cert-err34-c]
80*89a1d03eSRichard double d = atof(in); // to double
81*89a1d03eSRichard }
82*89a1d03eSRichard
f3(void)83*89a1d03eSRichard void f3(void) {
84*89a1d03eSRichard int i;
85*89a1d03eSRichard unsigned int u;
86*89a1d03eSRichard float f;
87*89a1d03eSRichard char str[32];
88*89a1d03eSRichard
89*89a1d03eSRichard // Test that we don't report multiple infractions for a single call.
90*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
91*89a1d03eSRichard scanf("%d%u%f", &i, &u, &f);
92*89a1d03eSRichard
93*89a1d03eSRichard // Test that we still catch infractions that are not the first specifier.
94*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: 'scanf' used to convert
95*89a1d03eSRichard scanf("%s%d", str, &i);
96*89a1d03eSRichard }
97*89a1d03eSRichard
do_not_diagnose(void)98*89a1d03eSRichard void do_not_diagnose(void) {
99*89a1d03eSRichard char str[32];
100*89a1d03eSRichard
101*89a1d03eSRichard scanf("%s", str); // Not a numerical conversion
102*89a1d03eSRichard scanf("%*d"); // Assignment suppressed
103*89a1d03eSRichard }
104