Skip to content

Commit fdbe736

Browse files
[analyzer] Harden RegionStoreManager::bindArray
Fixes #147686 by completing handling of literals and handling symbolic values similarly to bindStruct. CPP-6688
1 parent 7f763d9 commit fdbe736

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

clang/lib/StaticAnalyzer/Core/RegionStore.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2654,14 +2654,19 @@ RegionStoreManager::bindArray(LimitedRegionBindingsConstRef B,
26542654
SVal V = getBinding(B.asStore(), *MRV, R->getValueType());
26552655
return bindAggregate(B, R, V);
26562656
}
2657+
if (auto const *Value = Init.getAsInteger()) {
2658+
auto SafeValue = StateMgr.getBasicVals().getValue(*Value);
2659+
return bindAggregate(B, R, nonloc::ConcreteInt(SafeValue));
2660+
}
26572661

2658-
// Handle lazy compound values.
2662+
// Handle lazy compound values and symbolic values.
26592663
if (std::optional LCV = Init.getAs<nonloc::LazyCompoundVal>()) {
26602664
if (std::optional NewB = tryBindSmallArray(B, R, AT, *LCV))
26612665
return *NewB;
2662-
26632666
return bindAggregate(B, R, Init);
26642667
}
2668+
if (isa<nonloc::SymbolVal>(Init))
2669+
return bindAggregate(B, R, Init);
26652670

26662671
if (Init.isUnknown())
26672672
return bindAggregate(B, R, UnknownVal());

clang/test/Analysis/initializer.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,3 +610,44 @@ void top() {
610610
consume(parseMatchComponent());
611611
}
612612
} // namespace elementwise_copy_small_array_from_post_initializer_of_cctor
613+
614+
namespace gh147686 {
615+
// The problem reported in https://github.com/llvm/llvm-project/issues/147686
616+
// is sensitive to the initializer form: using parenthesis to initialize m_ptr
617+
// resulted in crashes when analyzing *m_ptr = '\0'; but using braces is fine.
618+
619+
struct A {
620+
A() : m_ptr(m_buf) { *m_ptr = '\0'; } // no-crash
621+
A(int overload) : m_ptr{m_buf} { *m_ptr = '\0'; }
622+
A(char src) : m_ptr(m_buf) { *m_ptr = src; } // no-crash
623+
A(char src, int overload) : m_ptr{m_buf} { *m_ptr = src; }
624+
char m_buf[64] = {0};
625+
char * m_ptr;
626+
};
627+
628+
void test1() {
629+
A a;
630+
clang_analyzer_eval(a.m_buf[0] == 0); // expected-warning{{TRUE}}
631+
// FIXME The next eval should result in TRUE.
632+
clang_analyzer_eval(*a.m_ptr == 0); // expected-warning{{UNKNOWN}}
633+
}
634+
635+
void test2() {
636+
A a(314);
637+
clang_analyzer_eval(a.m_buf[0] == 0); // expected-warning{{TRUE}}
638+
clang_analyzer_eval(*a.m_ptr == 0); // expected-warning{{TRUE}}
639+
}
640+
641+
void test3() {
642+
A a(0);
643+
clang_analyzer_eval(a.m_buf[0] == 0); // expected-warning{{TRUE}}
644+
clang_analyzer_eval(*a.m_ptr == 0); // expected-warning{{TRUE}}
645+
}
646+
647+
void test4() {
648+
A a(0, 314);
649+
clang_analyzer_eval(a.m_buf[0] == 0); // expected-warning{{TRUE}}
650+
clang_analyzer_eval(*a.m_ptr == 0); // expected-warning{{TRUE}}
651+
}
652+
653+
} // namespace gh147686

0 commit comments

Comments
 (0)