Skip to content

Commit 5a2f12f

Browse files
authored
Add library attribute for no-failure allocators (#7390)
For example GLib and GTK abort on most allocation failures, making the nullPointerOutOfMemory check produce lots of false positives. To fix this, introduce a new allocator attribute "no-fail" to notify that this allocator cannot fail and that this check is thus irrelevant for it.
1 parent 26788f4 commit 5a2f12f

File tree

10 files changed

+493
-460
lines changed

10 files changed

+493
-460
lines changed

cfg/cppcheck-cfg.rng

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
<ref name="DATA-EXTNAME"/>
2727
</element>
2828
<element name="alloc">
29+
<optional>
30+
<attribute name="no-fail"><ref name="DATA-BOOL"/></attribute>
31+
</optional>
2932
<optional>
3033
<attribute name="init"><ref name="DATA-BOOL"/></attribute>
3134
</optional>
@@ -38,6 +41,9 @@
3841
<ref name="DATA-EXTNAME"/>
3942
</element>
4043
<element name="realloc">
44+
<optional>
45+
<attribute name="no-fail"><ref name="DATA-BOOL"/></attribute>
46+
</optional>
4147
<optional>
4248
<attribute name="init"><ref name="DATA-BOOL"/></attribute>
4349
</optional>
@@ -69,6 +75,9 @@
6975
<ref name="DATA-EXTNAME"/>
7076
</element>
7177
<element name="alloc">
78+
<optional>
79+
<attribute name="no-fail"><ref name="DATA-BOOL"/></attribute>
80+
</optional>
7281
<optional>
7382
<attribute name="init"><ref name="DATA-BOOL"/></attribute>
7483
</optional>
@@ -78,6 +87,9 @@
7887
<ref name="DATA-EXTNAME"/>
7988
</element>
8089
<element name="realloc">
90+
<optional>
91+
<attribute name="no-fail"><ref name="DATA-BOOL"/></attribute>
92+
</optional>
8193
<optional>
8294
<attribute name="init"><ref name="DATA-BOOL"/></attribute>
8395
</optional>

cfg/gtk.cfg

Lines changed: 456 additions & 456 deletions
Large diffs are not rendered by default.

gui/cppchecklibrarydata.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ static CppcheckLibraryData::MemoryResource loadMemoryResource(QXmlStreamReader &
272272
if (elementName == "alloc" || elementName == "realloc") {
273273
CppcheckLibraryData::MemoryResource::Alloc alloc;
274274
alloc.isRealloc = (elementName == "realloc");
275+
alloc.noFail = (xmlReader.attributes().value("no-fail").toString() == "true");
275276
alloc.init = (xmlReader.attributes().value("init").toString() == "true");
276277
if (xmlReader.attributes().hasAttribute("arg")) {
277278
alloc.arg = xmlReader.attributes().value("arg").toInt();
@@ -723,6 +724,8 @@ static void writeMemoryResource(QXmlStreamWriter &xmlWriter, const CppcheckLibra
723724
xmlWriter.writeStartElement("alloc");
724725
}
725726
xmlWriter.writeAttribute("init", bool_to_string(alloc.init));
727+
if (alloc.noFail)
728+
xmlWriter.writeAttribute("no-fail", bool_to_string(alloc.noFail));
726729
if (alloc.arg != -1) {
727730
xmlWriter.writeAttribute("arg", QString("%1").arg(alloc.arg));
728731
}

gui/cppchecklibrarydata.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ class CppcheckLibraryData {
142142
struct Alloc {
143143
bool isRealloc{};
144144
bool init{};
145+
bool noFail{};
145146
int arg = -1; // -1: Has no optional "realloc-arg" attribute
146147
int reallocArg = -1; // -1: Has no optional "arg" attribute
147148
QString bufferSize;

gui/test/cppchecklibrarydata/files/memory_resource_valid.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<realloc init="false" buffer-size="malloc:2">realloc</realloc>
77
<alloc arg="2">UuidToString</alloc>
88
<dealloc arg="3">HeapFree</dealloc>
9+
<alloc init="false" no-fail="true" buffer-size="malloc">g_malloc</alloc>
910
</memory>
1011

1112
<resource>

gui/test/cppchecklibrarydata/testcppchecklibrarydata.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,38 +284,50 @@ void TestCppcheckLibraryData::memoryResourceValid()
284284
// Do size and content checks against swapped data.
285285
QCOMPARE(libraryData.memoryresource.size(), 2);
286286
QCOMPARE(libraryData.memoryresource[0].type, QString("memory"));
287-
QCOMPARE(libraryData.memoryresource[0].alloc.size(), 4);
287+
QCOMPARE(libraryData.memoryresource[0].alloc.size(), 5);
288288
QCOMPARE(libraryData.memoryresource[0].dealloc.size(), 1);
289289
QCOMPARE(libraryData.memoryresource[0].use.size(), 0);
290290

291291
QCOMPARE(libraryData.memoryresource[0].alloc[0].name, QString("malloc"));
292292
QCOMPARE(libraryData.memoryresource[0].alloc[0].bufferSize, QString("malloc"));
293293
QCOMPARE(libraryData.memoryresource[0].alloc[0].isRealloc, false);
294294
QCOMPARE(libraryData.memoryresource[0].alloc[0].init, false);
295+
QCOMPARE(libraryData.memoryresource[0].alloc[0].noFail, false);
295296
QCOMPARE(libraryData.memoryresource[0].alloc[0].arg, -1);
296297
QCOMPARE(libraryData.memoryresource[0].alloc[0].reallocArg, -1);
297298

298299
QCOMPARE(libraryData.memoryresource[0].alloc[1].name, QString("calloc"));
299300
QCOMPARE(libraryData.memoryresource[0].alloc[1].bufferSize, QString("calloc"));
300301
QCOMPARE(libraryData.memoryresource[0].alloc[1].isRealloc, false);
301302
QCOMPARE(libraryData.memoryresource[0].alloc[1].init, true);
303+
QCOMPARE(libraryData.memoryresource[0].alloc[1].noFail, false);
302304
QCOMPARE(libraryData.memoryresource[0].alloc[1].arg, -1);
303305
QCOMPARE(libraryData.memoryresource[0].alloc[1].reallocArg, -1);
304306

305307
QCOMPARE(libraryData.memoryresource[0].alloc[2].name, QString("realloc"));
306308
QCOMPARE(libraryData.memoryresource[0].alloc[2].bufferSize, QString("malloc:2"));
307309
QCOMPARE(libraryData.memoryresource[0].alloc[2].isRealloc, true);
308310
QCOMPARE(libraryData.memoryresource[0].alloc[2].init, false);
311+
QCOMPARE(libraryData.memoryresource[0].alloc[2].noFail, false);
309312
QCOMPARE(libraryData.memoryresource[0].alloc[2].arg, -1);
310313
QCOMPARE(libraryData.memoryresource[0].alloc[2].reallocArg, -1);
311314

312315
QCOMPARE(libraryData.memoryresource[0].alloc[3].name, QString("UuidToString"));
313316
QCOMPARE(libraryData.memoryresource[0].alloc[3].bufferSize.isEmpty(), true);
314317
QCOMPARE(libraryData.memoryresource[0].alloc[3].isRealloc, false);
315318
QCOMPARE(libraryData.memoryresource[0].alloc[3].init, false);
319+
QCOMPARE(libraryData.memoryresource[0].alloc[3].noFail, false);
316320
QCOMPARE(libraryData.memoryresource[0].alloc[3].arg, 2);
317321
QCOMPARE(libraryData.memoryresource[0].alloc[3].reallocArg, -1);
318322

323+
QCOMPARE(libraryData.memoryresource[0].alloc[4].name, QString("g_malloc"));
324+
QCOMPARE(libraryData.memoryresource[0].alloc[4].bufferSize, QString("malloc"));
325+
QCOMPARE(libraryData.memoryresource[0].alloc[4].isRealloc, false);
326+
QCOMPARE(libraryData.memoryresource[0].alloc[4].init, false);
327+
QCOMPARE(libraryData.memoryresource[0].alloc[4].noFail, true);
328+
QCOMPARE(libraryData.memoryresource[0].alloc[4].arg, -1);
329+
QCOMPARE(libraryData.memoryresource[0].alloc[4].reallocArg, -1);
330+
319331
QCOMPARE(libraryData.memoryresource[0].dealloc[0].name, QString("HeapFree"));
320332
QCOMPARE(libraryData.memoryresource[0].dealloc[0].arg, 3);
321333

@@ -328,6 +340,7 @@ void TestCppcheckLibraryData::memoryResourceValid()
328340
QCOMPARE(libraryData.memoryresource[1].alloc[0].bufferSize.isEmpty(), true);
329341
QCOMPARE(libraryData.memoryresource[1].alloc[0].isRealloc, false);
330342
QCOMPARE(libraryData.memoryresource[1].alloc[0].init, true);
343+
QCOMPARE(libraryData.memoryresource[1].alloc[0].noFail, false);
331344
QCOMPARE(libraryData.memoryresource[1].alloc[0].arg, 1);
332345
QCOMPARE(libraryData.memoryresource[1].alloc[0].reallocArg, -1);
333346

@@ -362,6 +375,7 @@ void TestCppcheckLibraryData::memoryResourceValid()
362375
QCOMPARE(lhs.alloc[num].bufferSize, rhs.alloc[num].bufferSize);
363376
QCOMPARE(lhs.alloc[num].isRealloc, rhs.alloc[num].isRealloc);
364377
QCOMPARE(lhs.alloc[num].init, rhs.alloc[num].init);
378+
QCOMPARE(lhs.alloc[num].noFail, rhs.alloc[num].noFail);
365379
QCOMPARE(lhs.alloc[num].arg, rhs.alloc[num].arg);
366380
QCOMPARE(lhs.alloc[num].reallocArg, rhs.alloc[num].reallocArg);
367381
}

lib/library.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ Library::Error Library::load(const tinyxml2::XMLDocument &doc)
369369
AllocFunc temp;
370370
temp.groupId = allocationId;
371371

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

lib/library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class CPPCHECKLIB Library {
8888
int bufferSizeArg2{};
8989
int reallocArg{};
9090
bool initData{};
91+
bool noFail{};
9192
};
9293

9394
/** get allocation info for function */

lib/valueflow.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7150,7 +7150,9 @@ static void valueFlowUnknownFunctionReturn(TokenList& tokenlist, const Settings&
71507150
continue;
71517151

71527152
if (const auto* f = settings.library.getAllocFuncInfo(tok->astOperand1())) {
7153-
if (settings.library.returnValueType(tok->astOperand1()).find('*') != std::string::npos) {
7153+
if (f->noFail) {
7154+
// Allocation function that cannot fail
7155+
} else if (settings.library.returnValueType(tok->astOperand1()).find('*') != std::string::npos) {
71547156
// Allocation function that returns a pointer
71557157
ValueFlow::Value value(0);
71567158
value.setPossible();

test/cfg/gtk.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,10 @@ void validCode(int argInt, GHashTableIter * hash_table_iter, GHashTable * hash_t
4646
g_printerr("err");
4747

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

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

0 commit comments

Comments
 (0)