Skip to content

Add library attribute for no-failure allocators #7390

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions cfg/cppcheck-cfg.rng
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
<ref name="DATA-EXTNAME"/>
</element>
<element name="alloc">
<optional>
<attribute name="no-fail"><ref name="DATA-BOOL"/></attribute>
</optional>
<optional>
<attribute name="init"><ref name="DATA-BOOL"/></attribute>
</optional>
Expand All @@ -38,6 +41,9 @@
<ref name="DATA-EXTNAME"/>
</element>
<element name="realloc">
<optional>
<attribute name="no-fail"><ref name="DATA-BOOL"/></attribute>
</optional>
<optional>
<attribute name="init"><ref name="DATA-BOOL"/></attribute>
</optional>
Expand Down Expand Up @@ -69,6 +75,9 @@
<ref name="DATA-EXTNAME"/>
</element>
<element name="alloc">
<optional>
<attribute name="no-fail"><ref name="DATA-BOOL"/></attribute>
</optional>
<optional>
<attribute name="init"><ref name="DATA-BOOL"/></attribute>
</optional>
Expand All @@ -78,6 +87,9 @@
<ref name="DATA-EXTNAME"/>
</element>
<element name="realloc">
<optional>
<attribute name="no-fail"><ref name="DATA-BOOL"/></attribute>
</optional>
<optional>
<attribute name="init"><ref name="DATA-BOOL"/></attribute>
</optional>
Expand Down
912 changes: 456 additions & 456 deletions cfg/gtk.cfg

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions gui/cppchecklibrarydata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ static CppcheckLibraryData::MemoryResource loadMemoryResource(QXmlStreamReader &
if (elementName == "alloc" || elementName == "realloc") {
CppcheckLibraryData::MemoryResource::Alloc alloc;
alloc.isRealloc = (elementName == "realloc");
alloc.noFail = (xmlReader.attributes().value("no-fail").toString() == "true");
alloc.init = (xmlReader.attributes().value("init").toString() == "true");
if (xmlReader.attributes().hasAttribute("arg")) {
alloc.arg = xmlReader.attributes().value("arg").toInt();
Expand Down Expand Up @@ -723,6 +724,8 @@ static void writeMemoryResource(QXmlStreamWriter &xmlWriter, const CppcheckLibra
xmlWriter.writeStartElement("alloc");
}
xmlWriter.writeAttribute("init", bool_to_string(alloc.init));
if (alloc.noFail)
xmlWriter.writeAttribute("no-fail", bool_to_string(alloc.noFail));
if (alloc.arg != -1) {
xmlWriter.writeAttribute("arg", QString("%1").arg(alloc.arg));
}
Expand Down
1 change: 1 addition & 0 deletions gui/cppchecklibrarydata.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ class CppcheckLibraryData {
struct Alloc {
bool isRealloc{};
bool init{};
bool noFail{};
int arg = -1; // -1: Has no optional "realloc-arg" attribute
int reallocArg = -1; // -1: Has no optional "arg" attribute
QString bufferSize;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<realloc init="false" buffer-size="malloc:2">realloc</realloc>
<alloc arg="2">UuidToString</alloc>
<dealloc arg="3">HeapFree</dealloc>
<alloc init="false" no-fail="true" buffer-size="malloc">g_malloc</alloc>
</memory>

<resource>
Expand Down
16 changes: 15 additions & 1 deletion gui/test/cppchecklibrarydata/testcppchecklibrarydata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,38 +284,50 @@ void TestCppcheckLibraryData::memoryResourceValid()
// Do size and content checks against swapped data.
QCOMPARE(libraryData.memoryresource.size(), 2);
QCOMPARE(libraryData.memoryresource[0].type, QString("memory"));
QCOMPARE(libraryData.memoryresource[0].alloc.size(), 4);
QCOMPARE(libraryData.memoryresource[0].alloc.size(), 5);
QCOMPARE(libraryData.memoryresource[0].dealloc.size(), 1);
QCOMPARE(libraryData.memoryresource[0].use.size(), 0);

QCOMPARE(libraryData.memoryresource[0].alloc[0].name, QString("malloc"));
QCOMPARE(libraryData.memoryresource[0].alloc[0].bufferSize, QString("malloc"));
QCOMPARE(libraryData.memoryresource[0].alloc[0].isRealloc, false);
QCOMPARE(libraryData.memoryresource[0].alloc[0].init, false);
QCOMPARE(libraryData.memoryresource[0].alloc[0].noFail, false);
QCOMPARE(libraryData.memoryresource[0].alloc[0].arg, -1);
QCOMPARE(libraryData.memoryresource[0].alloc[0].reallocArg, -1);

QCOMPARE(libraryData.memoryresource[0].alloc[1].name, QString("calloc"));
QCOMPARE(libraryData.memoryresource[0].alloc[1].bufferSize, QString("calloc"));
QCOMPARE(libraryData.memoryresource[0].alloc[1].isRealloc, false);
QCOMPARE(libraryData.memoryresource[0].alloc[1].init, true);
QCOMPARE(libraryData.memoryresource[0].alloc[1].noFail, false);
QCOMPARE(libraryData.memoryresource[0].alloc[1].arg, -1);
QCOMPARE(libraryData.memoryresource[0].alloc[1].reallocArg, -1);

QCOMPARE(libraryData.memoryresource[0].alloc[2].name, QString("realloc"));
QCOMPARE(libraryData.memoryresource[0].alloc[2].bufferSize, QString("malloc:2"));
QCOMPARE(libraryData.memoryresource[0].alloc[2].isRealloc, true);
QCOMPARE(libraryData.memoryresource[0].alloc[2].init, false);
QCOMPARE(libraryData.memoryresource[0].alloc[2].noFail, false);
QCOMPARE(libraryData.memoryresource[0].alloc[2].arg, -1);
QCOMPARE(libraryData.memoryresource[0].alloc[2].reallocArg, -1);

QCOMPARE(libraryData.memoryresource[0].alloc[3].name, QString("UuidToString"));
QCOMPARE(libraryData.memoryresource[0].alloc[3].bufferSize.isEmpty(), true);
QCOMPARE(libraryData.memoryresource[0].alloc[3].isRealloc, false);
QCOMPARE(libraryData.memoryresource[0].alloc[3].init, false);
QCOMPARE(libraryData.memoryresource[0].alloc[3].noFail, false);
QCOMPARE(libraryData.memoryresource[0].alloc[3].arg, 2);
QCOMPARE(libraryData.memoryresource[0].alloc[3].reallocArg, -1);

QCOMPARE(libraryData.memoryresource[0].alloc[4].name, QString("g_malloc"));
QCOMPARE(libraryData.memoryresource[0].alloc[4].bufferSize, QString("malloc"));
QCOMPARE(libraryData.memoryresource[0].alloc[4].isRealloc, false);
QCOMPARE(libraryData.memoryresource[0].alloc[4].init, false);
QCOMPARE(libraryData.memoryresource[0].alloc[4].noFail, true);
QCOMPARE(libraryData.memoryresource[0].alloc[4].arg, -1);
QCOMPARE(libraryData.memoryresource[0].alloc[4].reallocArg, -1);

QCOMPARE(libraryData.memoryresource[0].dealloc[0].name, QString("HeapFree"));
QCOMPARE(libraryData.memoryresource[0].dealloc[0].arg, 3);

Expand All @@ -328,6 +340,7 @@ void TestCppcheckLibraryData::memoryResourceValid()
QCOMPARE(libraryData.memoryresource[1].alloc[0].bufferSize.isEmpty(), true);
QCOMPARE(libraryData.memoryresource[1].alloc[0].isRealloc, false);
QCOMPARE(libraryData.memoryresource[1].alloc[0].init, true);
QCOMPARE(libraryData.memoryresource[1].alloc[0].noFail, false);
QCOMPARE(libraryData.memoryresource[1].alloc[0].arg, 1);
QCOMPARE(libraryData.memoryresource[1].alloc[0].reallocArg, -1);

Expand Down Expand Up @@ -362,6 +375,7 @@ void TestCppcheckLibraryData::memoryResourceValid()
QCOMPARE(lhs.alloc[num].bufferSize, rhs.alloc[num].bufferSize);
QCOMPARE(lhs.alloc[num].isRealloc, rhs.alloc[num].isRealloc);
QCOMPARE(lhs.alloc[num].init, rhs.alloc[num].init);
QCOMPARE(lhs.alloc[num].noFail, rhs.alloc[num].noFail);
QCOMPARE(lhs.alloc[num].arg, rhs.alloc[num].arg);
QCOMPARE(lhs.alloc[num].reallocArg, rhs.alloc[num].reallocArg);
}
Expand Down
1 change: 1 addition & 0 deletions lib/library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ Library::Error Library::load(const tinyxml2::XMLDocument &doc)
AllocFunc temp;
temp.groupId = allocationId;

temp.noFail = memorynode->BoolAttribute("no-fail", false);
temp.initData = memorynode->BoolAttribute("init", true);
temp.arg = memorynode->IntAttribute("arg", -1);

Expand Down
1 change: 1 addition & 0 deletions lib/library.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class CPPCHECKLIB Library {
int bufferSizeArg2{};
int reallocArg{};
bool initData{};
bool noFail{};
};

/** get allocation info for function */
Expand Down
4 changes: 3 additions & 1 deletion lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6975,7 +6975,9 @@ static void valueFlowUnknownFunctionReturn(TokenList& tokenlist, const Settings&
continue;

if (const auto* f = settings.library.getAllocFuncInfo(tok->astOperand1())) {
if (settings.library.returnValueType(tok->astOperand1()).find('*') != std::string::npos) {
if (f->noFail) {
// Allocation function that cannot fail
} else if (settings.library.returnValueType(tok->astOperand1()).find('*') != std::string::npos) {
// Allocation function that returns a pointer
ValueFlow::Value value(0);
value.setPossible();
Expand Down
2 changes: 0 additions & 2 deletions test/cfg/gtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,10 @@ void validCode(int argInt, GHashTableIter * hash_table_iter, GHashTable * hash_t
g_printerr("err");

GString * pGStr1 = g_string_new("test");
// cppcheck-suppress nullPointerOutOfMemory
g_string_append(pGStr1, "a");
g_string_free(pGStr1, TRUE);

gchar * pGchar1 = g_strconcat("a", "b", NULL);
// cppcheck-suppress nullPointerOutOfMemory
printf("%s", pGchar1);
g_free(pGchar1);

Expand Down
Loading