You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
ASSERT_EQUALS("[test.cpp:4]: (error) Read operation on a file that was opened only for writing.\n", errout.str());
}
voiduseClosedFile() {
check("void foo(FILE*& f) {\n"
" fclose(f);\n"
" fwrite(buffer, 5, 6, f);\n"
" clearerr(f);\n"
" fread(buffer, 5, 6, f);\n"
" ungetc('a', f);\n"
" ungetwc(L'a', f);\n"
" rewind(f);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Used file that is not opened.\n"
"[test.cpp:4]: (error) Used file that is not opened.\n"
"[test.cpp:5]: (error) Used file that is not opened.\n"
"[test.cpp:6]: (error) Used file that is not opened.\n"
"[test.cpp:7]: (error) Used file that is not opened.\n"
"[test.cpp:8]: (error) Used file that is not opened.\n", errout.str());
check("void foo(FILE*& f) {\n"
" if(!ferror(f)) {\n"
" fclose(f);\n"
" return;"
" }\n"
" fwrite(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo(FILE*& f) {\n"
" fclose(f);\n"
" f = fopen(name, \"r\");\n"
" fread(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo(FILE*& f) {\n"
" f = fopen(name, \"r\");\n"
" f = g;\n"
" fwrite(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo() {\n"
" FILE* f;\n"
" fwrite(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Used file that is not opened.\n", errout.str());
check("void foo() {\n"
" FILE* f(stdout);\n"
" fwrite(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo() {\n"// #3965
" FILE* f[3];\n"
" f[0] = fopen(name, mode);\n"
" fclose(f[0]);\n"
"}");
ASSERT_EQUALS("", errout.str());
// #4368: multiple functions
check("static FILE *fp = NULL;\n"
"\n"
"void close()\n"
"{\n"
" fclose(fp);\n"
"}\n"
"\n"
"void dump()\n"
"{\n"
" if (fp == NULL) return;\n"
" fprintf(fp, \"Here's the output.\\n\");\n"
"}\n"
"\n"
"int main()\n"
"{\n"
" fp = fopen(\"test.txt\", \"w\");\n"
" dump();\n"
" close();\n"
" return 0;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("static FILE *fp = NULL;\n"
"\n"
"void close()\n"
"{\n"
" fclose(fp);\n"
"}\n"
"\n"
"void dump()\n"
"{\n"
" fclose(fp);\n"
" fprintf(fp, \"Here's the output.\\n\");\n"
"}");
ASSERT_EQUALS("[test.cpp:11]: (error) Used file that is not opened.\n", errout.str());
// #4466
check("void chdcd_parse_nero(FILE *infile) {\n"
" switch (mode) {\n"
" case 0x0300:\n"
" fclose(infile);\n"
" return;\n"
" case 0x0500:\n"
" fclose(infile);\n"
" return;\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void chdcd_parse_nero(FILE *infile) {\n"
" switch (mode) {\n"
" case 0x0300:\n"
" fclose(infile);\n"
" exit(0);\n"
" case 0x0500:\n"
" fclose(infile);\n"
" return;\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
// #4649
check("void foo() {\n"
" struct {FILE *f1; FILE *f2;} a;\n"
" a.f1 = fopen(name,mode);\n"
" a.f2 = fopen(name,mode);\n"
" fclose(a.f1);\n"
" fclose(a.f2);\n"
"}");
ASSERT_EQUALS("", errout.str());
// #1473
check("void foo() {\n"
" FILE *a = fopen(\"aa\", \"r\");\n"
" while (fclose(a)) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Used file that is not opened.\n", errout.str());
// #6823
check("void foo() {\n"
" FILE f[2];\n"
" f[0] = fopen(\"1\", \"w\");\n"
" f[1] = fopen(\"2\", \"w\");\n"
" fclose(f[0]);\n"
" fclose(f[1]);\n"
"}");
ASSERT_EQUALS("", errout.str());
}
voidfileIOwithoutPositioning() {
check("void foo(FILE* f) {\n"
" fwrite(buffer, 5, 6, f);\n"
" fread(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Read and write operations without a call to a positioning function (fseek, fsetpos or rewind) or fflush in between result in undefined behaviour.\n", errout.str());
check("void foo(FILE* f) {\n"
" fread(buffer, 5, 6, f);\n"
" fwrite(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Read and write operations without a call to a positioning function (fseek, fsetpos or rewind) or fflush in between result in undefined behaviour.\n", errout.str());
check("void foo(FILE* f, bool read) {\n"
" if(read)\n"
" fread(buffer, 5, 6, f);\n"
" else\n"
" fwrite(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo(FILE* f) {\n"
" fread(buffer, 5, 6, f);\n"
" fflush(f);\n"
" fwrite(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo(FILE* f) {\n"
" fread(buffer, 5, 6, f);\n"
" rewind(f);\n"
" fwrite(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo(FILE* f) {\n"
" fread(buffer, 5, 6, f);\n"
" fsetpos(f, pos);\n"
" fwrite(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo(FILE* f) {\n"
" fread(buffer, 5, 6, f);\n"
" fseek(f, 0, SEEK_SET);\n"
" fwrite(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo(FILE* f) {\n"
" fread(buffer, 5, 6, f);\n"
" long pos = ftell(f);\n"
" fwrite(buffer, 5, 6, f);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Read and write operations without a call to a positioning function (fseek, fsetpos or rewind) or fflush in between result in undefined behaviour.\n", errout.str());
ASSERT_EQUALS("[test.cpp:9]: (error) Read and write operations without a call to a positioning function (fseek, fsetpos or rewind) or fflush in between result in undefined behaviour.\n", errout.str());
ASSERT_EQUALS("[test.cpp:9]: (error) Read and write operations without a call to a positioning function (fseek, fsetpos or rewind) or fflush in between result in undefined behaviour.\n", errout.str());
}
voidseekOnAppendedFile() {
check("void foo() {\n"
" FILE* f = fopen(\"\", \"a+\");\n"
" fseek(f, 0, SEEK_SET);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo() {\n"
" FILE* f = fopen(\"\", \"w\");\n"
" fseek(f, 0, SEEK_SET);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo() {\n"
" FILE* f = fopen(\"\", \"a\");\n"
" fseek(f, 0, SEEK_SET);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) Repositioning operation performed on a file opened in append mode has no effect.\n", errout.str());
check("void foo() {\n"
" FILE* f = fopen(\"\", \"a\");\n"
" fflush(f);\n"
"}");
ASSERT_EQUALS("", errout.str()); // #5578
check("void foo() {\n"
" FILE* f = fopen(\"\", \"a\");\n"
" fclose(f);\n"
" f = fopen(\"\", \"r\");\n"
" fseek(f, 0, SEEK_SET);\n"
"}");
ASSERT_EQUALS("", errout.str()); // #6566
}
voidfflushOnInputStream() {
check("void foo()\n"
"{\n"
" fflush(stdin);\n"
"}", false, true);
ASSERT_EQUALS("[test.cpp:3]: (portability) fflush() called on input stream 'stdin' may result in undefined behaviour on non-linux systems.\n", errout.str());
check("void foo()\n"
"{\n"
" fflush(stdout);\n"
"}", false, true);
ASSERT_EQUALS("", errout.str());
check("void foo(FILE*& f) {\n"
" f = fopen(path, \"r\");\n"
" fflush(f);\n"
"}", false, true);
ASSERT_EQUALS("[test.cpp:3]: (portability) fflush() called on input stream 'f' may result in undefined behaviour on non-linux systems.\n", errout.str());
check("void foo(FILE*& f) {\n"
" f = fopen(path, \"w\");\n"
" fflush(f);\n"
"}", false, true);
ASSERT_EQUALS("", errout.str());
check("void foo(FILE*& f) {\n"
" fflush(f);\n"
"}", false, true);
ASSERT_EQUALS("", errout.str());
}
voidtestScanf1() {
check("void foo() {\n"
" int a, b;\n"
" FILE *file = fopen(\"test\", \"r\");\n"
" a = fscanf(file, \"aa %s\", bar);\n"
" b = scanf(\"aa %S\", bar);\n"
" b = scanf(\"aa %ls\", bar);\n"
" sscanf(foo, \"%[^~]\", bar);\n"
" scanf(\"%dx%s\", &b, bar);\n"
" fclose(file);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (warning) fscanf() without field width limits can crash with huge input data.\n"
"[test.cpp:5]: (warning) scanf() without field width limits can crash with huge input data.\n"
"[test.cpp:6]: (warning) scanf() without field width limits can crash with huge input data.\n"
"[test.cpp:7]: (warning) sscanf() without field width limits can crash with huge input data.\n"
"[test.cpp:8]: (warning) scanf() without field width limits can crash with huge input data.\n", errout.str());
}
voidtestScanf2() {
check("void foo() {\n"
" scanf(\"%5s\", bar);\n"// Width specifier given
" scanf(\"%5[^~]\", bar);\n"// Width specifier given
" scanf(\"aa%%s\", bar);\n"// No %s
" scanf(\"aa%d\", &a);\n"// No %s
" scanf(\"aa%ld\", &a);\n"// No %s
" scanf(\"%*[^~]\");\n"// Ignore input
"}");
ASSERT_EQUALS("[test.cpp:4]: (warning) scanf format string requires 0 parameters but 1 is given.\n", errout.str());
}
voidtestScanf3() { // ticket #3494
check("void f() {\n"
" char str[8];\n"
" scanf(\"%7c\", str);\n"
" scanf(\"%8c\", str);\n"
" scanf(\"%9c\", str);\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Width 9 given in format string (no. 1) is larger than destination buffer 'str[8]', use %8c to prevent overflowing it.\n", errout.str());
}
voidtestScanf4() { // ticket #2553
check("void f()\n"
"{\n"
" char str [8];\n"
" scanf (\"%70s\",str);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Width 70 given in format string (no. 1) is larger than destination buffer 'str[8]', use %7s to prevent overflowing it.\n", errout.str());
}
#defineTEST_SCANF_CODE(format, type)\
"void f(){" type " x; scanf(\"" format "\", &x);}"
#defineTEST_SCANF_ERR(format, formatStr, type)\
"[test.cpp:1]: (warning) " format " in format string (no. 1) requires '" formatStr " *' but the argument type is '" type " *'.\n"
"[test.cpp:1]: (portability) " format " in format string (no. 1) requires '" formatStr " *' but the argument type is '" type " * {aka " akaType " *}'.\n"
"[test.cpp:1]: (portability) " format " in format string (no. 1) requires '" requiredType "' but the argument type is '" actualType " {aka " akaType "}'.\n"
ASSERT_EQUALS("[test.cpp:2]: (warning) scanf format string requires 0 parameters but 1 is given.\n"
"[test.cpp:3]: (warning) scanf format string requires 1 parameter but 2 are given.\n"
"[test.cpp:4]: (warning) fscanf format string requires 1 parameter but 2 are given.\n"
"[test.cpp:5]: (warning) scanf format string requires 2 parameters but 3 are given.\n", errout.str());
check("void foo() {\n"
" scanf(\"%1d\");\n"
" scanf(\"%1u%1u\", bar());\n"
" sscanf(bar, \"%1d%1d\", &foo);\n"
" scanf(\"%*1x %1x %29s\", &count);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (error) scanf format string requires 1 parameter but only 0 are given.\n"
"[test.cpp:3]: (error) scanf format string requires 2 parameters but only 1 is given.\n"
"[test.cpp:4]: (error) sscanf format string requires 2 parameters but only 1 is given.\n"
"[test.cpp:5]: (error) scanf format string requires 2 parameters but only 1 is given.\n", errout.str());
check("void foo() {\n"
" char input[10];\n"
" char output[5];\n"
" sscanf(input, \"%3s\", output);\n"
" sscanf(input, \"%4s\", output);\n"
" sscanf(input, \"%5s\", output);\n"
"}", false);
ASSERT_EQUALS("[test.cpp:6]: (error) Width 5 given in format string (no. 1) is larger than destination buffer 'output[5]', use %4s to prevent overflowing it.\n", errout.str());
check("void foo() {\n"
" char input[10];\n"
" char output[5];\n"
" sscanf(input, \"%s\", output);\n"
" sscanf(input, \"%3s\", output);\n"
" sscanf(input, \"%4s\", output);\n"
" sscanf(input, \"%5s\", output);\n"
"}", true);
ASSERT_EQUALS("[test.cpp:5]: (warning, inconclusive) Width 3 given in format string (no. 1) is smaller than destination buffer 'output[5]'.\n"
"[test.cpp:7]: (error) Width 5 given in format string (no. 1) is larger than destination buffer 'output[5]', use %4s to prevent overflowing it.\n"
"[test.cpp:4]: (warning) sscanf() without field width limits can crash with huge input data.\n", errout.str());
check("void foo() {\n"
" const size_t BUFLENGTH(2048);\n"
" typedef char bufT[BUFLENGTH];\n"
" bufT line= {0};\n"
" bufT projectId= {0};\n"
" const int scanrc=sscanf(line, \"Project(\\\"{%36s}\\\")\", projectId);\n"
" sscanf(input, \"%5s\", output);\n"
"}", true);
ASSERT_EQUALS("", errout.str());
check("void foo(unsigned int i) {\n"
" scanf(\"%h\", &i);\n"
" scanf(\"%hh\", &i);\n"
" scanf(\"%l\", &i);\n"
" scanf(\"%ll\", &i);\n"
" scanf(\"%j\", &i);\n"
" scanf(\"%z\", &i);\n"
" scanf(\"%t\", &i);\n"
" scanf(\"%L\", &i);\n"
" scanf(\"%I\", &i);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) 'h' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
"[test.cpp:3]: (warning) 'hh' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
"[test.cpp:4]: (warning) 'l' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
"[test.cpp:5]: (warning) 'll' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
"[test.cpp:6]: (warning) 'j' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
"[test.cpp:7]: (warning) 'z' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
"[test.cpp:8]: (warning) 't' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
"[test.cpp:9]: (warning) 'L' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
"[test.cpp:10]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n", errout.str());
// Unrecognized (and non-existent in standard library) specifiers.