Skip to content

Commit e7f0ee6

Browse files
authored
Merge branch 'danmar:main' into main
2 parents 2d5dde9 + 66078d3 commit e7f0ee6

35 files changed

Lines changed: 585 additions & 345 deletions

htmlreport/cppcheck-htmlreport

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,57 @@ HTML_HEAD = """
356356
}
357357
}
358358
359+
function reapplyFilters() {
360+
// Reapply ID filters
361+
var idToggles = document.querySelectorAll(".idToggle");
362+
for (var i = 1; i < idToggles.length; i++) {
363+
var cb = idToggles[i];
364+
var elements = document.querySelectorAll("." + cb.id);
365+
for (var j = 0; j < elements.length; j++) {
366+
elements[j].classList.toggle("id-filtered", !cb.checked);
367+
}
368+
}
369+
370+
// Reapply severity filters
371+
var sevToggles = document.querySelectorAll(".sev_toggle");
372+
for (var i = 0; i < sevToggles.length; i++) {
373+
var cb = sevToggles[i];
374+
var elements = document.querySelectorAll(".sev_" + cb.id);
375+
for (var j = 0; j < elements.length; j++) {
376+
elements[j].classList.toggle("severity-filtered", !cb.checked);
377+
}
378+
}
379+
380+
// Reapply classification filters
381+
var classToggles = document.querySelectorAll(".class_toggle");
382+
for (var i = 0; i < classToggles.length; i++) {
383+
var cb = classToggles[i];
384+
var elements = document.querySelectorAll(".class_" + cb.id);
385+
for (var j = 0; j < elements.length; j++) {
386+
elements[j].classList.toggle("classification-filtered", !cb.checked);
387+
}
388+
}
389+
390+
// Reapply tool filters
391+
var toolToggles = document.querySelectorAll(".tool_toggle");
392+
for (var i = 0; i < toolToggles.length; i++) {
393+
var cb = toolToggles[i];
394+
var elements;
395+
if (cb.id == "clang-tidy")
396+
elements = document.querySelectorAll("[class^=clang-tidy-]");
397+
else
398+
elements = document.querySelectorAll(".issue:not([class^=clang-tidy-])");
399+
400+
for (var j = 0; j < elements.length; j++) {
401+
elements[j].classList.toggle("tool-filtered", !cb.checked);
402+
}
403+
}
404+
405+
// Update file rows
406+
updateFileRows();
407+
}
408+
409+
window.addEventListener("pageshow", reapplyFilters);
359410
window.addEventListener("load", initExpandables);
360411
</script>
361412
</head>
@@ -494,9 +545,20 @@ def tr_str(td_th, line, id, cwe, severity, classification, guideline, message, t
494545
if classification:
495546
items.extend([classification, guideline])
496547
if htmlfile:
497-
ret += '<%s><a href="%s#line-%d">%d</a></%s>' % (td_th, htmlfile, line, line, td_th)
548+
if htmlfile.startswith("http://") or htmlfile.startswith("https://"):
549+
# GitHub/GitLab style line anchor
550+
href = f"{htmlfile.rstrip('#L1')}#L{line}"
551+
# Emit **line number with link**
552+
ret += f'<{td_th}><a href="{href}" target="_blank" rel="noopener noreferrer">{line}</a></{td_th}>'
553+
else:
554+
# local HTML annotated
555+
href = f"{htmlfile}#line-{line}"
556+
# Emit **line number with link**
557+
ret += f'<{td_th}><a href="{href}">{line}</a></{td_th}>'
558+
559+
# Emit id, cwe, severity, classification, ...
498560
for item in items:
499-
ret += '<%s>%s</%s>' % (td_th, item, td_th)
561+
ret += f'<{td_th}>{item}</{td_th}>'
500562
else:
501563
items.insert(0,line)
502564
for item in items:
@@ -675,7 +737,9 @@ def main() -> None:
675737
'written.')
676738
parser.add_argument('--source-dir', dest='source_dir',
677739
help='Base directory where source code files can be '
678-
'found.')
740+
'found, or a URL to a remote GitHub/GitLab '
741+
'repository including a branch, e.g. '
742+
'--source-dir=https://github.com/<username>/<repo>/blob/<branch>/')
679743
parser.add_argument('--add-author-information', dest='add_author_information',
680744
help='Blame information to include. '
681745
'Adds specified author information. '
@@ -705,6 +769,10 @@ def main() -> None:
705769
if options.source_dir:
706770
source_dir = options.source_dir
707771

772+
is_remote = False
773+
if source_dir.startswith("http://") or source_dir.startswith("https://"):
774+
is_remote = True
775+
708776
add_author_information = []
709777
if options.add_author_information:
710778
fields = [x.strip() for x in options.add_author_information.split(',')]
@@ -753,9 +821,14 @@ def main() -> None:
753821
for error in contentHandler.errors:
754822
filename = error['file']
755823
if filename not in files:
756-
files[filename] = {
757-
'errors': [], 'htmlfile': str(file_no) + '.html'}
758-
file_no = file_no + 1
824+
if is_remote:
825+
# Construct remote URL for GitHub/GitLab
826+
# tr_str() will use the actual line number, so we can just start with line 1
827+
remote_url = source_dir.rstrip('/') + '/' + filename + '#L1'
828+
files[filename] = {'errors': [], 'htmlfile': remote_url}
829+
else:
830+
files[filename] = {'errors': [], 'htmlfile': str(file_no) + '.html'}
831+
file_no += 1
759832
files[filename]['errors'].append(error)
760833

761834
# Make sure that the report directory is created if it doesn't exist.
@@ -795,6 +868,11 @@ def main() -> None:
795868
if filename == '':
796869
continue
797870

871+
if is_remote:
872+
# Remote source: do NOT generate local annotated HTML files.
873+
# The index will still point directly to GitHub/GitLab URLs.
874+
continue
875+
798876
source_filename = os.path.join(source_dir, filename)
799877
try:
800878
with io.open(source_filename, 'r', encoding=options.source_encoding) as input_file:

lib/astutils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3678,15 +3678,15 @@ bool isGlobalData(const Token *expr)
36783678
// TODO check if pointer points at local data
36793679
const Variable *lhsvar = tok->astOperand1()->variable();
36803680
const ValueType *lhstype = tok->astOperand1()->valueType();
3681-
if (lhsvar->isPointer()) {
3681+
if (lhsvar->isPointer() || !lhstype || lhstype->type == ValueType::Type::ITERATOR) {
36823682
globalData = true;
36833683
return ChildrenToVisit::none;
36843684
}
36853685
if (lhsvar->isArgument() && lhsvar->isArray()) {
36863686
globalData = true;
36873687
return ChildrenToVisit::none;
36883688
}
3689-
if (lhsvar->isArgument() && (!lhstype || (lhstype->type <= ValueType::Type::VOID && !lhstype->container))) {
3689+
if (lhsvar->isArgument() && lhstype->type <= ValueType::Type::VOID && !lhstype->container) {
36903690
globalData = true;
36913691
return ChildrenToVisit::none;
36923692
}

lib/check64bit.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,14 @@ static bool is32BitIntegerReturn(const Function* func, const Settings* settings)
4545
if (settings->platform.sizeof_pointer != 8)
4646
return false;
4747
const ValueType* vt = func->arg->valueType();
48-
return vt && vt->pointer == 0 && vt->isIntegral() && vt->typeSize(settings->platform) == 4;
48+
return vt && vt->pointer == 0 && vt->isIntegral() && vt->getSizeOf(*settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer) == 4;
49+
}
50+
51+
static bool isFunctionPointer(const Token* tok)
52+
{
53+
if (!tok || !tok->variable())
54+
return false;
55+
return Tokenizer::isFunctionPointer(tok->variable()->nameToken());
4956
}
5057

5158
void Check64BitPortability::pointerassignment()
@@ -120,7 +127,8 @@ void Check64BitPortability::pointerassignment()
120127
!tok->astOperand2()->isNumber() &&
121128
rhstype->pointer == 0U &&
122129
rhstype->originalTypeName.empty() &&
123-
rhstype->type == ValueType::Type::INT)
130+
rhstype->type == ValueType::Type::INT &&
131+
!isFunctionPointer(tok->astOperand1()))
124132
assignmentIntegerToAddressError(tok);
125133

126134
// Assign pointer to integer..

lib/checkbufferoverrun.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ static int getMinFormatStringOutputLength(const std::vector<const Token*> &param
9696
std::string digits_string;
9797
bool i_d_x_f_found = false;
9898
int parameterLength = 0;
99-
int inputArgNr = formatStringArgNr;
99+
nonneg int inputArgNr = formatStringArgNr;
100100
for (std::size_t i = 1; i + 1 < formatString.length(); ++i) {
101101
if (formatString[i] == '\\') {
102102
if (i < formatString.length() - 1 && formatString[i + 1] == '0')
@@ -229,7 +229,8 @@ static bool getDimensionsEtc(const Token * const arrayToken, const Settings &set
229229
Dimension dim;
230230
dim.known = value->isKnown();
231231
dim.tok = nullptr;
232-
const MathLib::bigint typeSize = array->valueType()->typeSize(settings.platform, array->valueType()->pointer > 1);
232+
const auto sizeOf = array->valueType()->pointer > 1 ? ValueType::SizeOf::Pointer : ValueType::SizeOf::Pointee;
233+
const size_t typeSize = array->valueType()->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, sizeOf);
233234
if (typeSize == 0)
234235
return false;
235236
dim.num = value->intvalue / typeSize;
@@ -585,7 +586,7 @@ ValueFlow::Value CheckBufferOverrun::getBufferSize(const Token *bufTok) const
585586
if (var->isPointerArray())
586587
v.intvalue = dim * mSettings->platform.sizeof_pointer;
587588
else {
588-
const MathLib::bigint typeSize = bufTok->valueType()->typeSize(mSettings->platform);
589+
const size_t typeSize = bufTok->valueType()->getSizeOf(*mSettings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointee);
589590
v.intvalue = dim * typeSize;
590591
}
591592

@@ -929,7 +930,7 @@ bool CheckBufferOverrun::isCtuUnsafeBufferUsage(const Settings &settings, const
929930
{
930931
if (!offset)
931932
return false;
932-
if (!argtok->valueType() || argtok->valueType()->typeSize(settings.platform) == 0)
933+
if (!argtok->valueType() || argtok->valueType()->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointee) == 0)
933934
return false;
934935
const Token *indexTok = nullptr;
935936
if (type == 1 && Token::Match(argtok, "%name% [") && argtok->astParent() == argtok->next() && !Token::simpleMatch(argtok->linkAt(1), "] ["))
@@ -942,7 +943,7 @@ bool CheckBufferOverrun::isCtuUnsafeBufferUsage(const Settings &settings, const
942943
return false;
943944
if (!indexTok->hasKnownIntValue())
944945
return false;
945-
offset->value = indexTok->getKnownIntValue() * argtok->valueType()->typeSize(settings.platform);
946+
offset->value = indexTok->getKnownIntValue() * argtok->valueType()->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointee);
946947
return true;
947948
}
948949

@@ -1102,7 +1103,7 @@ void CheckBufferOverrun::objectIndex()
11021103
continue;
11031104
}
11041105
if (obj->valueType() && var->valueType() && (obj->isCast() || (obj->isCpp() && isCPPCast(obj)) || obj->valueType()->pointer)) { // allow cast to a different type
1105-
const auto varSize = var->valueType()->typeSize(mSettings->platform);
1106+
const auto varSize = var->valueType()->getSizeOf(*mSettings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointee);
11061107
if (varSize == 0)
11071108
continue;
11081109
if (obj->valueType()->type != var->valueType()->type) {

lib/checkclass.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3459,9 +3459,7 @@ void CheckClass::checkReturnByReference()
34593459
const bool isView = isContainer && var->valueType()->container->view;
34603460
bool warn = isContainer && !isView;
34613461
if (!warn && !isView) {
3462-
const std::size_t size = ValueFlow::getSizeOf(*var->valueType(),
3463-
*mSettings,
3464-
ValueFlow::Accuracy::LowerBound);
3462+
const std::size_t size = var->valueType()->getSizeOf(*mSettings, ValueType::Accuracy::LowerBound, ValueType::SizeOf::Pointer);
34653463
if (size > 2 * mSettings->platform.sizeof_pointer)
34663464
warn = true;
34673465
}

lib/checkleakautovar.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,12 @@ void CheckLeakAutoVar::leakIfAllocated(const Token *vartok,
11491149
}
11501150
}
11511151

1152+
static bool isSafeCast(const ValueType* vt, const Settings& settings)
1153+
{
1154+
const size_t sizeOf = vt->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointee);
1155+
return sizeOf == 0 || sizeOf >= settings.platform.sizeof_pointer;
1156+
}
1157+
11521158
void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndOfScope)
11531159
{
11541160
const std::map<int, VarInfo::AllocInfo> &alloctype = varInfo.alloctype;
@@ -1182,8 +1188,7 @@ void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndO
11821188
while (tok3 && tok3->isCast() &&
11831189
(!tok3->valueType() ||
11841190
tok3->valueType()->pointer ||
1185-
(tok3->valueType()->typeSize(mSettings->platform) == 0) ||
1186-
(tok3->valueType()->typeSize(mSettings->platform) >= mSettings->platform.sizeof_pointer)))
1191+
isSafeCast(tok3->valueType(), *mSettings)))
11871192
tok3 = tok3->astOperand2() ? tok3->astOperand2() : tok3->astOperand1();
11881193
if (tok3 && tok3->varId() == varid)
11891194
tok2 = tok3->next();

lib/checkmemoryleak.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,8 +1071,8 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope)
10711071
const Variable* argvar = tok->function()->getArgumentVar(argnr);
10721072
if (!argvar || !argvar->valueType())
10731073
continue;
1074-
const MathLib::bigint argSize = argvar->valueType()->typeSize(mSettings->platform, /*p*/ true);
1075-
if (argSize <= 0 || argSize >= mSettings->platform.sizeof_pointer)
1074+
const size_t argSize = argvar->valueType()->getSizeOf(*mSettings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointee);
1075+
if (argSize == 0 || argSize >= mSettings->platform.sizeof_pointer)
10761076
continue;
10771077
}
10781078
functionCallLeak(arg, arg->str(), functionName);

lib/checkother.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,7 +1524,7 @@ static bool isLargeContainer(const Variable* var, const Settings& settings)
15241524
return false;
15251525
}
15261526
const ValueType vtElem = ValueType::parseDecl(vt->containerTypeToken, settings);
1527-
const auto elemSize = std::max<std::size_t>(ValueFlow::getSizeOf(vtElem, settings, ValueFlow::Accuracy::LowerBound), 1);
1527+
const auto elemSize = std::max<std::size_t>(vtElem.getSizeOf(settings, ValueType::Accuracy::LowerBound, ValueType::SizeOf::Pointer), 1);
15281528
const auto arraySize = var->dimension(0) * elemSize;
15291529
return arraySize > maxByValueSize;
15301530
}
@@ -1564,7 +1564,7 @@ void CheckOther::checkPassByReference()
15641564
// Ensure that it is a large object.
15651565
if (!var->type()->classScope)
15661566
inconclusive = true;
1567-
else if (!var->valueType() || ValueFlow::getSizeOf(*var->valueType(), *mSettings, ValueFlow::Accuracy::LowerBound) <= 2 * mSettings->platform.sizeof_pointer)
1567+
else if (!var->valueType() || var->valueType()->getSizeOf(*mSettings, ValueType::Accuracy::LowerBound, ValueType::SizeOf::Pointer) <= 2 * mSettings->platform.sizeof_pointer)
15681568
continue;
15691569
}
15701570
else
@@ -3327,7 +3327,8 @@ void CheckOther::checkRedundantCopy()
33273327
const Token* varTok = fScope->bodyEnd->tokAt(-2);
33283328
if (varTok->variable() && !varTok->variable()->isGlobal() &&
33293329
(!varTok->variable()->type() || !varTok->variable()->type()->classScope ||
3330-
(varTok->variable()->valueType() && ValueFlow::getSizeOf(*varTok->variable()->valueType(), *mSettings, ValueFlow::Accuracy::LowerBound) > 2 * mSettings->platform.sizeof_pointer)))
3330+
(varTok->variable()->valueType() &&
3331+
varTok->variable()->valueType()->getSizeOf(*mSettings, ValueType::Accuracy::LowerBound, ValueType::SizeOf::Pointer) > 2 * mSettings->platform.sizeof_pointer)))
33313332
redundantCopyError(startTok, startTok->str());
33323333
}
33333334
}
@@ -3447,7 +3448,7 @@ void CheckOther::checkIncompleteArrayFill()
34473448
if (size == 0 && var->valueType()->pointer)
34483449
size = mSettings->platform.sizeof_pointer;
34493450
else if (size == 0 && var->valueType())
3450-
size = ValueFlow::getSizeOf(*var->valueType(), *mSettings, ValueFlow::Accuracy::LowerBound);
3451+
size = var->valueType()->getSizeOf(*mSettings, ValueType::Accuracy::LowerBound, ValueType::SizeOf::Pointer);
34513452
const Token* tok3 = tok->next()->astOperand2()->astOperand1()->astOperand1();
34523453
if ((size != 1 && size != 100 && size != 0) || var->isPointer()) {
34533454
if (printWarning)
@@ -4430,8 +4431,7 @@ static UnionMember parseUnionMember(const Variable &var,
44304431
if (var.isArray()) {
44314432
size = var.dimension(0);
44324433
} else if (vt != nullptr) {
4433-
size = ValueFlow::getSizeOf(*vt, settings,
4434-
ValueFlow::Accuracy::ExactOrZero);
4434+
size = vt->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer);
44354435
}
44364436
return UnionMember(nameToken->str(), size);
44374437
}
@@ -4523,7 +4523,7 @@ static bool getBufAndOffset(const Token *expr, const Token *&buf, MathLib::bigin
45234523
bufToken = expr->astOperand1()->astOperand1();
45244524
offsetToken = expr->astOperand1()->astOperand2();
45254525
if (expr->astOperand1()->valueType())
4526-
elementSize = ValueFlow::getSizeOf(*expr->astOperand1()->valueType(), settings, ValueFlow::Accuracy::LowerBound);
4526+
elementSize = expr->astOperand1()->valueType()->getSizeOf(settings, ValueType::Accuracy::LowerBound, ValueType::SizeOf::Pointer);
45274527
} else if (Token::Match(expr, "+|-") && expr->isBinaryOp()) {
45284528
const bool pointer1 = (expr->astOperand1()->valueType() && expr->astOperand1()->valueType()->pointer > 0);
45294529
const bool pointer2 = (expr->astOperand2()->valueType() && expr->astOperand2()->valueType()->pointer > 0);
@@ -4532,13 +4532,13 @@ static bool getBufAndOffset(const Token *expr, const Token *&buf, MathLib::bigin
45324532
offsetToken = expr->astOperand2();
45334533
auto vt = *expr->astOperand1()->valueType();
45344534
--vt.pointer;
4535-
elementSize = ValueFlow::getSizeOf(vt, settings, ValueFlow::Accuracy::LowerBound);
4535+
elementSize = vt.getSizeOf(settings, ValueType::Accuracy::LowerBound, ValueType::SizeOf::Pointer);
45364536
} else if (!pointer1 && pointer2) {
45374537
bufToken = expr->astOperand2();
45384538
offsetToken = expr->astOperand1();
45394539
auto vt = *expr->astOperand2()->valueType();
45404540
--vt.pointer;
4541-
elementSize = ValueFlow::getSizeOf(vt, settings, ValueFlow::Accuracy::LowerBound);
4541+
elementSize = vt.getSizeOf(settings, ValueType::Accuracy::LowerBound, ValueType::SizeOf::Pointer);
45424542
} else {
45434543
return false;
45444544
}
@@ -4547,7 +4547,7 @@ static bool getBufAndOffset(const Token *expr, const Token *&buf, MathLib::bigin
45474547
*offset = 0;
45484548
auto vt = *expr->valueType();
45494549
--vt.pointer;
4550-
elementSize = ValueFlow::getSizeOf(vt, settings, ValueFlow::Accuracy::LowerBound);
4550+
elementSize = vt.getSizeOf(settings, ValueType::Accuracy::LowerBound, ValueType::SizeOf::Pointer);
45514551
if (elementSize > 0) {
45524552
*offset *= elementSize;
45534553
if (sizeValue)

0 commit comments

Comments
 (0)