diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..2c9ee9f38 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,64 @@ +name: "CodeQL" + +on: + pull_request: + branches: [master] + +jobs: + analyze: + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: 'c-cpp' + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + libcmocka-dev libcurl4-openssl-dev libgcrypt20-dev libglib2.0-dev \ + libgpgme-dev libgtk-3-dev libmicrohttpd-dev libncursesw5-dev \ + libnotify-dev libotr5-dev libreadline-dev libsignal-protocol-c-dev \ + libomemo-c-dev libssl-dev libtool libxss-dev meson ninja-build \ + pkg-config python3-dev python-dev-is-python3 libsqlite3-dev \ + libgdk-pixbuf-2.0-dev libqrencode-dev libenchant-2-dev \ + autoconf autoconf-archive automake cmake expect + + - name: Install stabber and libstrophe + run: | + git clone --depth 1 https://github.com/profanity-im/stabber /tmp/stabber + cd /tmp/stabber && ./bootstrap.sh && ./configure --prefix=/usr && make -j$(nproc) && sudo make install + + git clone --depth 1 https://github.com/strophe/libstrophe /tmp/libstrophe + cd /tmp/libstrophe && ./bootstrap.sh && ./configure --prefix=/usr && make -j$(nproc) && sudo make install + + - name: Build for Analysis + run: | + meson setup build_codeql \ + -Dnotifications=enabled \ + -Dpython-plugins=enabled \ + -Dc-plugins=enabled \ + -Dotr=enabled \ + -Dpgp=enabled \ + -Domemo=enabled \ + -Domemo-qrcode=enabled \ + -Dicons-and-clipboard=enabled \ + -Dgdk-pixbuf=enabled \ + -Dxscreensaver=enabled \ + -Dspellcheck=enabled \ + -Dtests=false + meson compile -C build_codeql + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:c-cpp" diff --git a/.github/workflows/functional-tests.yml b/.github/workflows/functional-tests.yml new file mode 100644 index 000000000..f9cbfae09 --- /dev/null +++ b/.github/workflows/functional-tests.yml @@ -0,0 +1,80 @@ +name: Build + +on: + push: + branches: [master] + pull_request: + branches: [master] + +concurrency: + group: ${{ github.workflow }}-func-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + functional-tests: + runs-on: ubuntu-latest + name: ubuntu | func | signal + steps: + - uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + libcmocka-dev libcurl4-openssl-dev libgcrypt20-dev libglib2.0-dev \ + libgpgme-dev libgtk-3-dev libmicrohttpd-dev libncursesw5-dev \ + libnotify-dev libotr5-dev libreadline-dev libsignal-protocol-c-dev \ + libomemo-c-dev libssl-dev libtool libxss-dev meson ninja-build \ + pkg-config python3-dev python-dev-is-python3 libsqlite3-dev \ + libgdk-pixbuf-2.0-dev libqrencode-dev libenchant-2-dev \ + autoconf autoconf-archive automake cmake expect + + - name: Install stabber + run: | + git clone --depth 1 https://github.com/profanity-im/stabber /tmp/stabber + cd /tmp/stabber + ./bootstrap.sh + ./configure --prefix=/usr + make -j$(nproc) + sudo make install + + - name: Install libstrophe (master) + run: | + git clone --depth 1 https://github.com/strophe/libstrophe /tmp/libstrophe + cd /tmp/libstrophe + ./bootstrap.sh + ./configure --prefix=/usr + make -j$(nproc) + sudo make install + + - name: Configure and Build + run: | + # Use --buildtype=debugoptimized (-O2) for fast execution. + # Explicitly disable sanitizers to avoid the performance penalty. + meson setup build_run \ + --buildtype=debugoptimized \ + -Db_sanitize=none \ + -Dnotifications=enabled \ + -Dpython-plugins=enabled \ + -Dc-plugins=enabled \ + -Dotr=enabled \ + -Dpgp=enabled \ + -Domemo=enabled \ + -Domemo-qrcode=enabled \ + -Dicons-and-clipboard=enabled \ + -Dgdk-pixbuf=enabled \ + -Dxscreensaver=enabled \ + -Dspellcheck=enabled \ + -Dtests=true + meson compile -C build_run profanity:executable functionaltests + + - name: Verify Profanity Binary + run: | + ./build_run/profanity --version + + - name: Run Functional Tests + env: + TERM: xterm + LC_ALL: C.UTF-8 + run: | + ./build_run/functionaltests diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 70650a312..c00466570 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -237,7 +237,6 @@ Functional tests use [stabber](https://github.com/profanity-im/stabber) to simul **Performance Note:** It is highly recommended to run functional tests **without** sanitizers (**ASan** and **UBSan**). These sanitizers add significant overhead that can cause functional tests to time out or take an excessively long time to complete. * **Meson:** Ensure `-Db_sanitize=none` is set in your build configuration. You can check your current configuration with `meson configure build_run | grep b_sanitize`. -* **Autotools:** Ensure your `CFLAGS` does not contain `-fsanitize=address` or `-fsanitize=undefined`. To run functional tests, you need the same dependencies as unit tests (`cmocka`) plus `stabber` and `libutil`. @@ -288,6 +287,20 @@ scan-build meson setup build_run scan-build meson compile -C build_run ``` +### Runtime Analysis with Sanitizers +Developers and testers should compile and run Profanity with **AddressSanitizer (ASan)** and **UndefinedBehaviorSanitizer (UBSan)** enabled. While static analysis can find potential issues in the source code, sanitizers monitor the application while it is actually running. + +By running the application and exercising specific features, you trigger real world code paths that might contain memory leaks, buffer overflows, or undefined behavior that only manifest at runtime. + +To build with sanitizers enabled and enable debug logging: +```bash +meson setup build_run -Db_sanitize=address,undefined +meson compile -C build_run +./build_run/profanity -l DEBUG +``` + +**Performance Note:** Sanitizers add significant overhead. + ### Finding typos We include a `.codespellrc` configuration file for `codespell` in the root directory. Before committing it might make sense to run `codespell` to see if you made any typos. diff --git a/scripts/build-configuration-matrix.sh b/scripts/build-configuration-matrix.sh index 06651f108..6a3c3dc96 100755 --- a/scripts/build-configuration-matrix.sh +++ b/scripts/build-configuration-matrix.sh @@ -94,7 +94,7 @@ fi if [[ "$ARCH" == linux* ]]; then echo -e "${YELLOW}--> Running Valgrind check with full features ${BACKEND_OPT} ${EXTRA_ARGS}${NC}" rm -rf build_valgrind - meson setup build_valgrind ${tests[0]} ${BACKEND_OPT} -Dtests=true -Db_sanitize=address,undefined ${EXTRA_ARGS} + meson setup build_valgrind ${tests[0]} ${BACKEND_OPT} -Dtests=true -Db_sanitize=undefined ${EXTRA_ARGS} meson compile -C build_valgrind meson test -C build_valgrind "unit tests" --print-errorlogs --wrap=valgrind || echo "Valgrind issues detected" rm -rf build_valgrind diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index fa76b277a..9e13450d8 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2142,6 +2142,7 @@ static const struct cmd_t command_defs[] = { "/account set me status dnd", "/account set me dnd -1", "/account set me clientid \"Profanity 0.42 (Dev)\"", + "/account set me eval_password \"pass \\\"Test Accounts/my user\\\"\"", "/account rename me chattyme", "/account clear me pgpkeyid") }, diff --git a/src/tools/editor.c b/src/tools/editor.c index bf9e9c4cc..f762e7584 100644 --- a/src/tools/editor.c +++ b/src/tools/editor.c @@ -128,7 +128,9 @@ launch_editor(gchar* initial_content, void (*callback)(gchar* content, void* dat return TRUE; } else if (pid == 0) { // Child process: Inherits TTY from parent - execvp(editor_argv[0], editor_argv); + if (editor_argv && editor_argv[0]) { + execvp(editor_argv[0], editor_argv); + } _exit(EXIT_FAILURE); }