|  | // Refer issue 55019 for more details. | 
|  | // A supplemental test case of pr22954.c for other functions modeled in | 
|  | // the CStringChecker. | 
|  |  | 
|  | // RUN: %clang_analyze_cc1 %s -verify \ | 
|  | // RUN:   -analyzer-checker=core \ | 
|  | // RUN:   -analyzer-checker=unix \ | 
|  | // RUN:   -analyzer-checker=debug.ExprInspection | 
|  |  | 
|  | #include "Inputs/system-header-simulator.h" | 
|  | #include "Inputs/system-header-simulator-cxx.h" | 
|  |  | 
|  | void *malloc(size_t); | 
|  | void free(void *); | 
|  |  | 
|  | struct mystruct { | 
|  | void *ptr; | 
|  | char arr[4]; | 
|  | }; | 
|  |  | 
|  | void clang_analyzer_dump(const void *); | 
|  |  | 
|  | // CStringChecker::memsetAux | 
|  | void fmemset() { | 
|  | mystruct x; | 
|  | x.ptr = malloc(1); | 
|  | clang_analyzer_dump(x.ptr); // expected-warning {{HeapSymRegion}} | 
|  | memset(x.arr, 0, sizeof(x.arr)); | 
|  | clang_analyzer_dump(x.ptr); // expected-warning {{HeapSymRegion}} | 
|  | free(x.ptr);                // no-leak-warning | 
|  | } | 
|  |  | 
|  | // CStringChecker::evalCopyCommon | 
|  | void fmemcpy() { | 
|  | mystruct x; | 
|  | x.ptr = malloc(1); | 
|  | clang_analyzer_dump(x.ptr); // expected-warning {{HeapSymRegion}} | 
|  | memcpy(x.arr, "hi", 2); | 
|  | clang_analyzer_dump(x.ptr); // expected-warning {{HeapSymRegion}} | 
|  | free(x.ptr);                // no-leak-warning | 
|  | } | 
|  |  | 
|  | // CStringChecker::evalStrcpyCommon | 
|  | void fstrcpy() { | 
|  | mystruct x; | 
|  | x.ptr = malloc(1); | 
|  | clang_analyzer_dump(x.ptr); // expected-warning {{HeapSymRegion}} | 
|  | strcpy(x.arr, "hi"); | 
|  | clang_analyzer_dump(x.ptr); // expected-warning {{HeapSymRegion}} | 
|  | free(x.ptr);                // no-leak-warning | 
|  | } | 
|  |  | 
|  | void fstrncpy() { | 
|  | mystruct x; | 
|  | x.ptr = malloc(1); | 
|  | clang_analyzer_dump(x.ptr); // expected-warning {{HeapSymRegion}} | 
|  | strncpy(x.arr, "hi", sizeof(x.arr)); | 
|  | clang_analyzer_dump(x.ptr); // expected-warning {{HeapSymRegion}} | 
|  | free(x.ptr);                // no-leak-warning | 
|  | } | 
|  |  | 
|  | // CStringChecker::evalStrsep | 
|  | void fstrsep() { | 
|  | mystruct x; | 
|  | x.ptr = malloc(1); | 
|  | clang_analyzer_dump(x.ptr); // expected-warning {{HeapSymRegion}} | 
|  | char *p = x.arr; | 
|  | (void)strsep(&p, "x"); | 
|  | clang_analyzer_dump(x.ptr); // expected-warning {{HeapSymRegion}} | 
|  | free(x.ptr);                // no-leak-warning | 
|  | } | 
|  |  | 
|  | // CStringChecker::evalStdCopyCommon | 
|  | void fstdcopy() { | 
|  | mystruct x; | 
|  | x.ptr = new char; | 
|  | clang_analyzer_dump(x.ptr); // expected-warning {{HeapSymRegion}} | 
|  |  | 
|  | const char *p = "x"; | 
|  | std::copy(p, p + 1, x.arr); | 
|  |  | 
|  | // FIXME: As we currently cannot know whether the copy overflows, the checker | 
|  | // invalidates the entire `x` object. When the copy size through iterators | 
|  | // can be correctly modeled, we can then update the verify direction from | 
|  | // SymRegion to HeapSymRegion as this std::copy call never overflows and | 
|  | // hence the pointer `x.ptr` shall not be invalidated. | 
|  | clang_analyzer_dump(x.ptr);       // expected-warning {{SymRegion}} | 
|  | delete static_cast<char*>(x.ptr); // no-leak-warning | 
|  | } |