Skip to content
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
28 changes: 28 additions & 0 deletions .github/workflows/static-code-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: static-code-analysis

on: [push, pull_request]

jobs:
cppcheck:
name: Cppcheck
runs-on: ubuntu-latest
env:
extra-args: >-
-i src/modules/decklink/darwin
-i src/modules/decklink/linux
-i src/modules/decklink/win
-i src/modules/glaxnimate/glaxnimate/
-i src/modules/plus/ebur128/
-i src/modules/xml/common.c
-i src/win32/strptime.c
--include=src/framework/mlt_log.h
--include=src/framework/mlt_types.h
--library=cppcheck.cfg
--suppress=ctuOneDefinitionRuleViolation
--suppress=syntaxError:src/modules/xml/common.c
steps:
- uses: actions/checkout@v4
- name: Install Cppcheck
run: sudo apt-get -qq -y install cppcheck
- name: Run Cppcheck
run: cppcheck src/ -j $(nproc) --force --inline-suppr --library=qt --error-exitcode=1 --template="::{severity} file={file},line={line},col={column}::{message}" ${{ env.extra-args }}
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ option(GPL3 "Enable GPLv3 components" ON)
option(BUILD_TESTING "Enable tests" OFF)
option(BUILD_DOCS "Enable Doxygen documentation" OFF)
option(CLANG_FORMAT "Enable Clang Format" ON)
option(BUILD_TESTS_WITH_QT6 "Build test against Qt 6" OFF)
option(BUILD_TESTS_WITH_QT6 "Build test against Qt 6" ON)

option(MOD_AVFORMAT "Enable avformat module" ON)
option(MOD_DECKLINK "Enable DeckLink module" ON)
Expand Down
5 changes: 5 additions & 0 deletions cppcheck.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0"?>
<def format="2">
<define name="VERSION" value="&quot;cppcheck&quot;"/>
<define name="__int64" value="long long"/>
</def>
16 changes: 16 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,19 @@ codespell:
codespell -w -q 3 \
-L shotcut,sav,boundry,percentil,readded,uint,ith,sinc,amin,childs,seeked,writen \
-S ChangeLog,cJSON.c,cJSON.h,RtAudio.cpp,RtAudio.h,*.rej,mlt_wrap.*

cppcheck:
cppcheck src/ --force --quiet --inline-suppr --library=qt --error-exitcode=1 \
-j $(shell nproc) \
-i src/modules/decklink/darwin \
-i src/modules/decklink/linux \
-i src/modules/decklink/win \
-i src/modules/glaxnimate/glaxnimate/ \
-i src/modules/plus/ebur128/ \
-i src/modules/xml/common.c \
-i src/win32/strptime.c \
--include=src/framework/mlt_log.h \
--include=src/framework/mlt_types.h \
--library=cppcheck.cfg \
--suppress=ctuOneDefinitionRuleViolation \
--suppress=syntaxError:src/modules/xml/common.c
9 changes: 8 additions & 1 deletion src/framework/mlt_animation.c
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,14 @@ char *mlt_animation_serialize_cut_tf(mlt_animation self,
while (used + item_len + 2 > size) // +2 for ';' and NULL
{
size += 1000;
ret = realloc(ret, size);
char *tmp = realloc(ret, size);
if (!tmp) {
free(ret);
mlt_property_close(item.property);
mlt_property_close(time_property);
return NULL;
}
ret = tmp;
}

// Append item delimiter (;) if needed.
Expand Down
4 changes: 2 additions & 2 deletions src/framework/mlt_image.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ mlt_colorspace mlt_image_colorspace_id(const char *name)
if (!value && strcmp(name, "0"))
value = -1; // strtol returned an error;

for (int i = 0; i < sizeof(colorspaces); i++) {
for (int i = 0; i < sizeof(colorspaces) / sizeof(colorspaces[0]); i++) {
const char *s = mlt_image_colorspace_name(colorspaces[i]);
if (value == colorspaces[i] || !strcmp(s, name))
return colorspaces[i];
Expand Down Expand Up @@ -463,7 +463,7 @@ mlt_color_primaries mlt_image_color_pri_id(const char *name)
if (!value && strcmp(name, "0"))
value = -1; // strtol returned an error;

for (int i = 0; name && i < sizeof(primaries); i++) {
for (int i = 0; name && i < sizeof(primaries) / sizeof(primaries[0]); i++) {
const char *s = mlt_image_color_pri_name(primaries[i]);
if (value == primaries[i] || !strcmp(s, name))
return primaries[i];
Expand Down
2 changes: 2 additions & 0 deletions src/framework/mlt_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,10 @@ static void *pool_fetch(mlt_pool self)
release->references = 1;

// Determine the ptr
// The memory is not leaked - it's returned via ptr
ptr = (char *) release + sizeof(struct mlt_release_s);
}
// cppcheck-suppress memleak
}

// Unlock the pool
Expand Down
76 changes: 54 additions & 22 deletions src/framework/mlt_property.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* \brief Property class definition
* \see mlt_property_s
*
* Copyright (C) 2003-2024 Meltytech, LLC
* Copyright (C) 2003-2025 Meltytech, LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -37,6 +37,17 @@
#include <stdlib.h>
#include <string.h>

// Platforms with native strtod_l support
#if defined(__GLIBC__) || defined(__APPLE__) || (defined(HAVE_STRTOD_L) && !defined(__OpenBSD__))
#define HAVE_LOCALE_STRTOD_L 1
#endif

// Platforms requiring manual locale handling (excluding Windows)
#if !defined(__GLIBC__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(HAVE_STRTOD_L) \
&& !defined(__OpenBSD__)
#define NEED_LOCALE_SAVE_RESTORE 1
#endif

/** Bit pattern used internally to indicated representations available.
*/

Expand Down Expand Up @@ -318,8 +329,7 @@ static int time_clock_to_frames(mlt_property self, const char *s, double fps, ml
s = copy;
pos = strrchr(s, ':');

#if !defined(__GLIBC__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(HAVE_STRTOD_L) \
&& !defined(__OpenBSD__)
#ifdef NEED_LOCALE_SAVE_RESTORE
char *orig_localename = NULL;
if (locale) {
// Protect damaging the global locale from a temporary locale on another thread.
Expand All @@ -334,7 +344,7 @@ static int time_clock_to_frames(mlt_property self, const char *s, double fps, ml
#endif

if (pos) {
#if defined(__GLIBC__) || defined(__APPLE__) || defined(HAVE_STRTOD_L) && !defined(__OpenBSD__)
#ifdef HAVE_LOCALE_STRTOD_L
if (locale)
seconds = strtod_l(pos + 1, NULL, locale);
else
Expand All @@ -350,16 +360,15 @@ static int time_clock_to_frames(mlt_property self, const char *s, double fps, ml
minutes = atoi(s);
}
} else {
#if defined(__GLIBC__) || defined(__APPLE__) || defined(HAVE_STRTOD_L) && !defined(__OpenBSD__)
#ifdef HAVE_LOCALE_STRTOD_L
if (locale)
seconds = strtod_l(s, NULL, locale);
else
#endif
seconds = strtod(s, NULL);
}

#if !defined(__GLIBC__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(HAVE_STRTOD_L) \
&& !defined(__OpenBSD__)
#ifdef NEED_LOCALE_SAVE_RESTORE
if (locale) {
// Restore the current locale
setlocale(LC_NUMERIC, orig_localename);
Expand Down Expand Up @@ -513,22 +522,47 @@ int mlt_property_get_int(mlt_property self, double fps, mlt_locale_t locale)
static double mlt_property_atof(mlt_property self, double fps, mlt_locale_t locale)
{
const char *value = self->prop_string;
#ifdef NEED_LOCALE_SAVE_RESTORE
char *orig_localename = NULL;
#endif

if (fps > 0 && strchr(value, ':')) {
#ifdef NEED_LOCALE_SAVE_RESTORE
if (locale) {
// Protect damaging the global locale from a temporary locale on another thread.
pthread_mutex_lock(&self->mutex);

// Get the current locale
orig_localename = strdup(setlocale(LC_NUMERIC, NULL));

// Set the new locale
setlocale(LC_NUMERIC, locale);
}
#endif
double result;
if (strchr(value, '.') || strchr(value, ','))
return time_clock_to_frames(self, value, fps, locale);
result = time_clock_to_frames(self, value, fps, locale);
else
return time_code_to_frames(self, value, fps);
result = time_code_to_frames(self, value, fps);

#ifdef NEED_LOCALE_SAVE_RESTORE
if (locale) {
// Restore the current locale
setlocale(LC_NUMERIC, orig_localename);
free(orig_localename);
pthread_mutex_unlock(&self->mutex);
}
#endif
return result;
} else {
char *end = NULL;
double result;

#if defined(__GLIBC__) || defined(__APPLE__) || defined(HAVE_STRTOD_L) && !defined(__OpenBSD__)
#ifdef HAVE_LOCALE_STRTOD_L
if (locale)
result = strtod_l(value, &end, locale);
else
#elif !defined(_WIN32)
char *orig_localename = NULL;
if (locale) {
// Protect damaging the global locale from a temporary locale on another thread.
pthread_mutex_lock(&self->mutex);
Expand All @@ -545,8 +579,7 @@ static double mlt_property_atof(mlt_property self, double fps, mlt_locale_t loca
if (end && end[0] == '%')
result /= 100.0;

#if !defined(__GLIBC__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(HAVE_STRTOD_L) \
&& !defined(__OpenBSD__)
#ifdef NEED_LOCALE_SAVE_RESTORE
if (locale) {
// Restore the current locale
setlocale(LC_NUMERIC, orig_localename);
Expand Down Expand Up @@ -1156,13 +1189,15 @@ int mlt_property_is_numeric(mlt_property self, mlt_locale_t locale)
// If not already numeric but string is numeric.
if ((!result && self->types & mlt_prop_string) && self->prop_string) {
char *p = NULL;
#ifdef NEED_LOCALE_SAVE_RESTORE
char *orig_localename = NULL;
#endif

#if defined(__GLIBC__) || defined(__APPLE__) || defined(HAVE_STRTOD_L) && !defined(__OpenBSD__)
#ifdef HAVE_LOCALE_STRTOD_L
if (locale)
strtod_l(self->prop_string, &p, locale);
else
#elif !defined(_WIN32)
char *orig_localename = NULL;
if (locale) {
// Protect damaging the global locale from a temporary locale on another thread.
pthread_mutex_lock(&self->mutex);
Expand All @@ -1177,8 +1212,7 @@ int mlt_property_is_numeric(mlt_property self, mlt_locale_t locale)

strtod(self->prop_string, &p);

#if !defined(__GLIBC__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(HAVE_STRTOD_L) \
&& !defined(__OpenBSD__)
#ifdef NEED_LOCALE_SAVE_RESTORE
if (locale) {
// Restore the current locale
setlocale(LC_NUMERIC, orig_localename);
Expand Down Expand Up @@ -1893,8 +1927,7 @@ mlt_rect mlt_property_get_rect(mlt_property self, mlt_locale_t locale)
char *p = NULL;
int count = 0;

#if !defined(__GLIBC__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(HAVE_STRTOD_L) \
&& !defined(__OpenBSD__)
#ifdef NEED_LOCALE_SAVE_RESTORE
char *orig_localename = NULL;
if (locale) {
// Protect damaging the global locale from a temporary locale on another thread.
Expand All @@ -1910,7 +1943,7 @@ mlt_rect mlt_property_get_rect(mlt_property self, mlt_locale_t locale)

while (*value) {
double temp;
#if defined(__GLIBC__) || defined(__APPLE__) || defined(HAVE_STRTOD_L) && !defined(__OpenBSD__)
#ifdef HAVE_LOCALE_STRTOD_L
if (locale)
temp = strtod_l(value, &p, locale);
else
Expand Down Expand Up @@ -1951,8 +1984,7 @@ mlt_rect mlt_property_get_rect(mlt_property self, mlt_locale_t locale)
count++;
}

#if !defined(__GLIBC__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(HAVE_STRTOD_L) \
&& !defined(__OpenBSD__)
#ifdef NEED_LOCALE_SAVE_RESTORE
if (locale) {
// Restore the current locale
setlocale(LC_NUMERIC, orig_localename);
Expand Down
1 change: 1 addition & 0 deletions src/modules/avformat/producer_avformat.c
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,7 @@ static int seek_video(producer_avformat self,
timestamp -= 2 / av_q2d(self->video_time_base);
if (timestamp < 0)
timestamp = 0;
// cppcheck-suppress syntaxError
mlt_log_debug(MLT_PRODUCER_SERVICE(producer),
"seeking timestamp %" PRId64 " position " MLT_POSITION_FMT
" expected " MLT_POSITION_FMT " last_pos %" PRId64 "\n",
Expand Down
9 changes: 7 additions & 2 deletions src/modules/gdk/producer_pango.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,14 @@ mlt_producer producer_pango_init(const char *filename)
while (fgets(line, 80, f)) {
size += strlen(line) + 1;
if (markup) {
markup = realloc(markup, size);
if (markup)
char *new_markup = realloc(markup, size);
if (new_markup) {
markup = new_markup;
strcat(markup, line);
} else {
// Allocation failed: keep existing content and stop appending
break;
}
} else {
markup = strdup(line);
}
Expand Down
4 changes: 4 additions & 0 deletions src/modules/plus/filter_loudness_meter.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ static void analyze_audio(mlt_filter filter, void *buffer, int samples)
prev_peak = peak;
}
}
// cppcheck-suppress invalidFunctionArg
mlt_properties_set_double(properties, "max_peak", 20 * log10(max_peak));
// cppcheck-suppress invalidFunctionArg
mlt_properties_set_double(properties, "peak", 20 * log10(prev_peak));
}

Expand All @@ -171,7 +173,9 @@ static void analyze_audio(mlt_filter filter, void *buffer, int samples)
prev_peak = peak;
}
}
// cppcheck-suppress invalidFunctionArg
mlt_properties_set_double(properties, "max_true_peak", 20 * log10(max_peak));
// cppcheck-suppress invalidFunctionArg
mlt_properties_set_double(properties, "true_peak", 20 * log10(prev_peak));
}

Expand Down
1 change: 1 addition & 0 deletions src/modules/qt/filter_audiowaveform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ mlt_filter filter_audiowaveform_init(mlt_profile profile,
if (filter && pdata) {
if (!createQApplicationIfNeeded(MLT_FILTER_SERVICE(filter))) {
mlt_filter_close(filter);
free(pdata);
return NULL;
}

Expand Down
10 changes: 8 additions & 2 deletions src/modules/qt/producer_qtext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -518,9 +518,15 @@ mlt_producer producer_qtext_init(mlt_profile profile,
while (fgets(line, 80, f)) {
size += strlen(line) + 1;
if (tmp) {
tmp = (char *) realloc(tmp, size);
if (tmp)
// Use a temporary pointer to avoid losing the original buffer on realloc failure
char *newtmp = (char *) realloc(tmp, size);
if (newtmp) {
tmp = newtmp;
strcat(tmp, line);
} else {
// Allocation failed: keep existing content and stop appending
break;
}
} else {
tmp = strdup(line);
}
Expand Down
8 changes: 4 additions & 4 deletions src/modules/qt/typewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,9 +509,9 @@ int TypeWriter::parseMacro(const std::string &line, uint &i, uint &frame)
if (pos2 != substr.npos)
s = substr.substr(pos, pos2 - pos);
else
s = substr.substr(pos, -1);
s = substr.substr(pos);
} else {
s = substr.substr(pos, -1);
s = substr.substr(pos);
}

insertString(s, frame);
Expand Down Expand Up @@ -578,9 +578,9 @@ int TypeWriter::parseMacro(const std::string &line, uint &i, uint &frame)
if (pos2 != substr.npos)
s = substr.substr(pos, pos2 - pos);
else
s = substr.substr(pos, -1);
s = substr.substr(pos);
} else {
s = substr.substr(pos, -1);
s = substr.substr(pos);
}

insertString(s, frame);
Expand Down
1 change: 1 addition & 0 deletions src/modules/xine/deinterlace.c
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,7 @@ void deinterlace_yuv( uint8_t *pdst, uint8_t *psrc[],
deinterlace_linearblend_yuv(pdst,psrc,width,height);
break;
default:
// cppcheck-suppress preprocessorErrorDirective
lprintf("unknown method %d.\n",method);
break;
}
Expand Down
Loading