| // RUN: %clang_analyze_cc1 -verify %s \ | |
| // RUN: -analyzer-checker=core,alpha.unix.cstring | |
| //===----------------------------------------------------------------------===// | |
| // mempcpy() using character array. This is the easiest case, as memcpy | |
| // intepretrs the dst and src buffers as character arrays (regardless of their | |
| // actual type). | |
| //===----------------------------------------------------------------------===// | |
| typedef typeof(sizeof(int)) size_t; | |
| void clang_analyzer_eval(int); | |
| void *memcpy(void *restrict s1, const void *restrict s2, size_t n); | |
| void memcpy_array_fully_uninit(char *dst) { | |
| char buf[10]; | |
| memcpy(dst, buf, 10); // expected-warning{{The first element of the 2nd argument is undefined}} | |
| // expected-note@-1{{Other elements might also be undefined}} | |
| (void)buf; | |
| } | |
| void memcpy_array_partially_uninit(char *dst) { | |
| char buf[10]; | |
| buf[0] = 'i'; | |
| memcpy(dst, buf, 10); // expected-warning{{The last accessed element (at index 9) in the 2nd argument is undefined}} | |
| // expected-note@-1{{Other elements might also be undefined}} | |
| (void)buf; | |
| } | |
| void memcpy_array_only_init_portion(char *dst) { | |
| char buf[10]; | |
| buf[0] = 'i'; | |
| memcpy(dst, buf, 1); | |
| (void)buf; | |
| } | |
| void memcpy_array_partially_init_error(char *dst) { | |
| char buf[10]; | |
| buf[0] = 'i'; | |
| memcpy(dst, buf, 2); // expected-warning{{The last accessed element (at index 1) in the 2nd argument is undefined}} | |
| // expected-note@-1{{Other elements might also be undefined}} | |
| (void)buf; | |
| } | |
| // The interesting case here is that the portion we're copying is initialized, | |
| // but not the whole matrix. We need to be careful to extract buf[1], and not | |
| // buf when trying to peel region layers off from the source argument. | |
| void memcpy_array_from_matrix(char *dst) { | |
| char buf[2][2]; | |
| buf[1][0] = 'i'; | |
| buf[1][1] = 'j'; | |
| // FIXME: This is a FP -- we mistakenly retrieve the first element of buf, | |
| // instead of the first element of buf[1]. getLValueElement simply peels off | |
| // another ElementRegion layer, when in this case it really shouldn't. | |
| memcpy(dst, buf[1], 2); // expected-warning{{The first element of the 2nd argument is undefined}} | |
| // expected-note@-1{{Other elements might also be undefined}} | |
| (void)buf; | |
| } | |
| //===----------------------------------------------------------------------===// | |
| // mempcpy() using non-character arrays. | |
| //===----------------------------------------------------------------------===// | |
| void *mempcpy(void *restrict s1, const void *restrict s2, size_t n); | |
| void memcpy_int_array_fully_init() { | |
| int src[] = {1, 2, 3, 4}; | |
| int dst[5] = {0}; | |
| int *p; | |
| p = mempcpy(dst, src, 4 * sizeof(int)); | |
| clang_analyzer_eval(p == &dst[4]); | |
| } | |
| void memcpy_int_array_fully_init2(int *dest) { | |
| int t[] = {1, 2, 3}; | |
| memcpy(dest, t, sizeof(t)); | |
| } | |
| //===----------------------------------------------------------------------===// | |
| // mempcpy() using nonarrays. | |
| //===----------------------------------------------------------------------===// | |
| struct st { | |
| int i; | |
| int j; | |
| }; | |
| void mempcpy_struct_partially_uninit() { | |
| struct st s1 = {0}; | |
| struct st s2; | |
| struct st *p1; | |
| struct st *p2; | |
| p1 = (&s2) + 1; | |
| // FIXME: Maybe ask UninitializedObjectChecker whether s1 is fully | |
| // initialized? | |
| p2 = mempcpy(&s2, &s1, sizeof(struct st)); | |
| clang_analyzer_eval(p1 == p2); | |
| } | |
| void mempcpy_struct_fully_uninit() { | |
| struct st s1; | |
| struct st s2; | |
| // FIXME: Maybe ask UninitializedObjectChecker whether s1 is fully | |
| // initialized? | |
| mempcpy(&s2, &s1, sizeof(struct st)); | |
| } | |
| // Creduced crash. In this case, an symbolicregion is wrapped in an | |
| // elementregion for the src argument. | |
| void *ga_copy_strings_from_0; | |
| void *memmove(); | |
| void alloc(); | |
| void ga_copy_strings() { | |
| int i = 0; | |
| for (;; ++i) | |
| memmove(alloc, ((char **)ga_copy_strings_from_0)[i], 1); | |
| } | |
| // Creduced crash. In this case, retrieving the Loc for the first element failed. | |
| char mov_mdhd_language_map[][4] = {}; | |
| int ff_mov_lang_to_iso639_code; | |
| char *ff_mov_lang_to_iso639_to; | |
| void ff_mov_lang_to_iso639() { | |
| memcpy(ff_mov_lang_to_iso639_to, | |
| mov_mdhd_language_map[ff_mov_lang_to_iso639_code], 4); | |
| } |