| // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -verify %s | |
| typedef decltype(sizeof(int)) size_t; | |
| void clang_analyzer_eval(bool); | |
| char *strncpy(char *dest, const char *src, size_t x); | |
| constexpr int initB = 100; | |
| struct Base { | |
| int b; | |
| Base(): b(initB) {} | |
| }; | |
| // issue 143807 | |
| struct strncpyTestClass: public Base { | |
| int *m_ptr; | |
| char m_buff[1000]; | |
| void KnownLen(char *src) { | |
| m_ptr = new int; | |
| strncpy(m_buff, src, sizeof(m_buff)); // known len but unknown src size | |
| delete m_ptr; // no warning | |
| } | |
| void KnownSrcLen(size_t n) { | |
| m_ptr = new int; | |
| strncpy(m_buff, "xyz", n); // known src size but unknown len | |
| delete m_ptr; // no warning | |
| } | |
| }; | |
| void strncpyTest(char *src, size_t n) { | |
| strncpyTestClass rep; | |
| rep.KnownLen(src); | |
| rep.KnownSrcLen(n); | |
| clang_analyzer_eval(rep.b == initB); // expected-warning{{TRUE}} | |
| } | |
| size_t strlcpy(char *dest, const char *src, size_t size); | |
| struct strlcpyTestClass: public Base { | |
| int *m_ptr; | |
| char m_buff[1000]; | |
| void KnownLen(char *src) { | |
| m_ptr = new int; | |
| strlcpy(m_buff, src, sizeof(m_buff)); // known len but unknown src size | |
| delete m_ptr; // no warning | |
| } | |
| void KnownSrcLen(size_t n) { | |
| m_ptr = new int; | |
| strlcpy(m_buff, "xyz", n); // known src size but unknown len | |
| delete m_ptr; // no warning | |
| } | |
| }; | |
| void strlcpyTest(char *src, size_t n) { | |
| strlcpyTestClass rep; | |
| rep.KnownLen(src); | |
| rep.KnownSrcLen(n); | |
| clang_analyzer_eval(rep.b == initB); // expected-warning{{TRUE}} | |
| } | |
| char *strncat(char *s1, const char *s2, size_t n); | |
| struct strncatTestClass: public Base { | |
| int *m_ptr; | |
| char m_buff[1000]; | |
| void KnownLen(char *src) { | |
| m_ptr = new int; | |
| strncat(m_buff, src, sizeof(m_buff) - 1); // known len but unknown src size | |
| delete m_ptr; // no warning | |
| } | |
| void KnownSrcLen(size_t n) { | |
| m_ptr = new int; | |
| strncat(m_buff, "xyz", n); // known src size but unknown len | |
| delete m_ptr; // no warning | |
| } | |
| }; | |
| void strncatTest(char *src, size_t n) { | |
| strncatTestClass rep; | |
| rep.KnownLen(src); | |
| rep.KnownSrcLen(n); | |
| clang_analyzer_eval(rep.b == initB); // expected-warning{{TRUE}} | |
| } | |
| struct strncatReportOutOfBoundTestClass { | |
| int *m_ptr; | |
| char m_buff[1000]; | |
| void KnownLen(char *src) { | |
| m_ptr = new int; | |
| // expected-warning@+1{{String concatenation function overflows the destination buffer}} | |
| strncat(m_buff, src, sizeof(m_buff)); // known len but unknown src size | |
| delete m_ptr; // no warning | |
| } | |
| }; | |
| void strncatReportOutOfBoundTest(char *src, size_t n) { | |
| strncatReportOutOfBoundTestClass rep; | |
| rep.KnownLen(src); | |
| } | |
| size_t strlcat(char *dst, const char *src, size_t size); | |
| struct strlcatTestClass: public Base { | |
| int *m_ptr; | |
| char m_buff[1000]; | |
| void KnownLen(char *src) { | |
| m_ptr = new int; | |
| strlcat(m_buff, src, sizeof(m_buff)); // known len but unknown src size | |
| delete m_ptr; // no warning | |
| } | |
| void KnownSrcLen(size_t n) { | |
| m_ptr = new int; | |
| strlcat(m_buff, "xyz", n); // known src size but unknown len | |
| delete m_ptr; // no warning | |
| } | |
| }; | |
| void strlcatTest(char *src, size_t n) { | |
| strlcatTestClass rep; | |
| rep.KnownLen(src); | |
| rep.KnownSrcLen(n); | |
| clang_analyzer_eval(rep.b == initB); // expected-warning{{TRUE}} | |
| } |