Compare commits

...

20 Commits

Author SHA1 Message Date
7359e30c3e adjust cmake for new toxcore files 2024-01-15 23:43:47 +01:00
5effe64474 Merge commit '61accfe1846e1f857fcdf84d27fb3d6e78fb46a3' 2024-01-15 23:32:23 +01:00
61accfe184 Squashed 'external/toxcore/c-toxcore/' changes from 73d9b845a3..e2c01e457b
e2c01e457b refactor: Use enum-specific pack functions for enum values.
afc472402b refactor: Factor out union pack switch from event packer.
6caa7ce4b1 cleanup: Move the 2-element array pack out of individual events.
687af81f20 cleanup: Remove empty test doing nothing.
fcf5882428 test: Add printf log statement to group_moderation_test.
b4d8826228 cleanup: Remove old type-ordered event getters.
8c35e0fefb feat: add ngc events
97bdd83937 refactor: Make event dispatch ordered by receive time.
001d00ab30 fix: dont resolve to ipv6 addresses when its disabled
d3b935f63f fix(test): tests use ipv6 by default, even with USE_IPV6 set to 0
29fc5ea1f7 chore: add clangd files to .gitignore
d30c81acbc refactor: Move file streaming test to its own file.
acdc67387b fix(ci): window builds now build in parallel
REVERT: 73d9b845a3 cleanup: Remove old type-ordered event getters.
REVERT: b0840cc02d feat: add ngc events
REVERT: 7df9a51349 refactor: Make event dispatch ordered by receive time.

git-subtree-dir: external/toxcore/c-toxcore
git-subtree-split: e2c01e457bfb8a59537175c8fe17ca9ab1c9e3e1
2024-01-15 23:32:23 +01:00
2f44996edc Merge commit 'b1fe0644843f5d08cd203bb5d4cdb923172f247b' 2024-01-14 21:51:01 +01:00
b1fe064484 Squashed 'external/toxcore/c-toxcore/' changes from 6d634674a9..73d9b845a3
73d9b845a3 cleanup: Remove old type-ordered event getters.
b0840cc02d feat: add ngc events
7df9a51349 refactor: Make event dispatch ordered by receive time.
bcb6592af5 test: Add C++ classes wrapping system interfaces.
4cea4f9ca4 fix: Make all the fuzzers work again, and add a test for protodump.
c4e209ea1d refactor: Factor out malloc+memcpy into memdup.
87bcc4322d fix: Remove fatal error for non-erroneous case
REVERT: 6d634674a9 cleanup: Remove old type-ordered event getters.
REVERT: d1d48d1dfc feat: add ngc events
REVERT: 994ffecc6b refactor: Make event dispatch ordered by receive time.

git-subtree-dir: external/toxcore/c-toxcore
git-subtree-split: 73d9b845a310c3f56d2d6d77ed56b93d84256d6e
2024-01-14 21:51:01 +01:00
18ca88a0d4 asan in flake 2024-01-14 21:48:41 +01:00
565aa4b7eb update deps and adopt 2024-01-14 18:50:23 +01:00
b117da5ccf add compute powersave extreme 2024-01-13 18:38:12 +01:00
8eb4892b49 Squashed 'external/toxcore/c-toxcore/' changes from 8f0d505f9a..6d634674a9
6d634674a9 cleanup: Remove old type-ordered event getters.
d1d48d1dfc feat: add ngc events
994ffecc6b refactor: Make event dispatch ordered by receive time.
812f931d5f fix: Make sure there's enough space for CONSUME1 in fuzzers.
50f1b30fa9 test: Add fuzz tests to the coverage run.
df76f5cf47 chore: Move from gcov to llvm source-based coverage.
072e3beb3f fix: issues with packet broadcast error reporting
6b6718e4d2 cleanup: Make group packet entry creation less error-prone
5b9c420ce1 refactor: packet broadcast functions now return errors
af4cb31028 refactor: Use `operator==` for equality tests of `Node_format`.
9592d590cf refactor(test): Slightly nicer C++ interface to tox Random.
c66e10fb7a refactor: Minor refactoring of get_close_nodes functions.
ebc9643862 fix: don't pass garbage data buffer to packet send functions
32b68cffca cleanup: Some more test cleanups, removing overly smart code.
0426624dcb refactor: Assign malloc return to a local variable first.
afc38f2458 test: Add more unit tests for `add_to_list`.
05ce5c1ab9 test: Add "infer" CI check to github, remove from circle.
REVERT: 8f0d505f9a feat: add ngc events
REVERT: 9b8216e70c refactor: Make event dispatch ordered by receive time.

git-subtree-dir: external/toxcore/c-toxcore
git-subtree-split: 6d634674a929edb0ab70689dcbcb195b3547be13
2024-01-12 21:30:48 +01:00
82fe4c3dd7 Merge commit '8eb4892b4976e82e020d0e30dcf8f0705b76bb4e' 2024-01-12 21:30:48 +01:00
78b0e9a77f more small fixes 2024-01-12 19:04:50 +01:00
7fa6aa7ac2 forgot to update plugin 2024-01-12 18:51:29 +01:00
20b4cdc5f1 sync and delivery (and unused read) states and other smaller refactors 2024-01-12 16:45:52 +01:00
7c576dd4d0 make fade less noticable 2024-01-10 14:17:29 +01:00
f6cda522ca correct message order 2024-01-09 22:38:13 +01:00
3d2f5b644b make toxcore work 2024-01-09 20:36:06 +01:00
9ace11a0e2 Squashed 'external/toxcore/c-toxcore/' changes from f1df709b87..8f0d505f9a
8f0d505f9a feat: add ngc events
9b8216e70c refactor: Make event dispatch ordered by receive time.
814c12a6f4 cleanup: Add dynamically derived array sizes to the API.
226b23be12 cleanup: Add explicit array sizes to toxencryptsave.
ef33cb4de0 cleanup: Add Toxav alias for ToxAV.
1da723b34d cleanup: Make Tox_Options a typedef.
b148a2afff chore: Simplify msvc build using vcpkg.
5cac6d7eb1 cleanup: Move `tox_get_system` out of the public API.
c9ca4007e3 refactor: Align group message sending with other send functions.
6c6c0b1b1b cleanup: Make setters take non-const `Tox *`.
a76f758d70 cleanup: Mark arrays in the tox API as `[]` instead of `*`.
baf6d1f6cf cleanup: Make array params in toxav `[]` instead of `*`.
79f55bd06a cleanup: Put the size of fixed arrays into the API types.
1e73698db2 cleanup: Add typedefs for public API int identifiers.
cac074c57f chore: Add fetch-sha256 script to update bootstrap node hash.
32576656bb Make the comment capitalization uniform
aff4dda17c Spellcheck tox-bootstrapd
40b5fbbe9d chore: Remove settings.yml in favour of hs-github-tools.
ebafd51be7 chore: Use GPL license with https.
0e42752f0f cleanup: Move all vptr-to-ptr casts to the beginning of a function.
5407384211 cleanup: Use github actions matrix to simplify CI.
82d8265688 fix: Use QueryPerformanceCounter on windows for monotonic time.
1224e656e3 chore: Add `net_(new|kill)_strerror` to cppcheck's allocators.
6a90ddfe4e cleanup: Run clang-tidy on headers, as well.
bd930cc80a cleanup: Make TCP connection failures a warning instead of error.
fad6e4e173 cleanup: Make all .c files include the headers they need.
ef4897a898 cleanup: Upgrade to clang-tidy-17 and fix some warnings.
REVERT: f1df709b87 feat: add ngc events
REVERT: 1b6c907235 refactor: Make event dispatch ordered by receive time.

git-subtree-dir: external/toxcore/c-toxcore
git-subtree-split: 8f0d505f9a598cc41c682178e1589bcc01efe9cb
2024-01-09 16:39:05 +01:00
6104d3b6d1 Merge commit '9ace11a0e2843cbde4af2b6ff7b49bcc6d429f78' 2024-01-09 16:39:05 +01:00
f637c7c942 make fade respect fps 2024-01-09 16:30:27 +01:00
afb886ea7c default to reduced fps 2024-01-09 15:57:20 +01:00
243 changed files with 4667 additions and 4280 deletions

View File

@@ -134,6 +134,8 @@ add_library(toxcore STATIC
${TOX_DIR}toxcore/tox.h ${TOX_DIR}toxcore/tox.h
${TOX_DIR}toxcore/tox_private.c ${TOX_DIR}toxcore/tox_private.c
${TOX_DIR}toxcore/tox_private.h ${TOX_DIR}toxcore/tox_private.h
${TOX_DIR}toxcore/tox_pack.h
${TOX_DIR}toxcore/tox_pack.c
${TOX_DIR}toxcore/tox_unpack.c ${TOX_DIR}toxcore/tox_unpack.c
${TOX_DIR}toxcore/tox_unpack.h ${TOX_DIR}toxcore/tox_unpack.h
${TOX_DIR}toxcore/util.c ${TOX_DIR}toxcore/util.c

View File

@@ -15,9 +15,7 @@ workflows:
- ubsan - ubsan
# Static analysis # Static analysis
- clang-analyze - clang-analyze
- clang-tidy
- cpplint - cpplint
- infer
- static-analysis - static-analysis
jobs: jobs:
@@ -70,6 +68,7 @@ jobs:
cmake cmake
git git
libconfig-dev libconfig-dev
libgmock-dev
libgtest-dev libgtest-dev
libopus-dev libopus-dev
libsodium-dev libsodium-dev
@@ -103,27 +102,6 @@ jobs:
- run: git submodule update --init --recursive - run: git submodule update --init --recursive
- run: CC=clang .circleci/cmake-ubsan - run: CC=clang .circleci/cmake-ubsan
infer:
working_directory: ~/work
docker:
- image: toxchat/infer
steps:
- run: *apt_install
- checkout
- run: git submodule update --init --recursive
- run: infer --no-progress-bar -- cc
auto_tests/auto_test_support.c
auto_tests/lossless_packet_test.c
testing/misc_tools.c
toxav/*.c
toxcore/*.c
toxcore/*/*.c
toxencryptsave/*.c
third_party/cmp/*.c
-lpthread
$(pkg-config --cflags --libs libsodium opus vpx)
static-analysis: static-analysis:
working_directory: ~/work working_directory: ~/work
docker: docker:
@@ -154,24 +132,6 @@ jobs:
- run: git submodule update --init --recursive - run: git submodule update --init --recursive
- run: other/analysis/run-clang-analyze - run: other/analysis/run-clang-analyze
clang-tidy:
working_directory: ~/work
docker:
- image: ubuntu
steps:
- run: *apt_install
- run:
apt-get install -y --no-install-recommends
ca-certificates
clang-tidy-14
- checkout
- run: git submodule update --init --recursive
- run:
other/analysis/run-clang-tidy ||
other/analysis/run-clang-tidy ||
other/analysis/run-clang-tidy
cpplint: cpplint:
working_directory: ~/work working_directory: ~/work
docker: docker:

View File

@@ -1,4 +1,5 @@
# vim:ft=yaml # vim:ft=yaml
HeaderFilterRegex: "/c-toxcore/[^/]+/[^.].+"
CheckOptions: CheckOptions:
- key: readability-identifier-naming.ClassCase - key: readability-identifier-naming.ClassCase
value: Camel_Snake_Case value: Camel_Snake_Case
@@ -35,6 +36,12 @@ CheckOptions:
value: lower_case value: lower_case
- key: llvmlibc-restrict-system-libc-headers.Includes - key: llvmlibc-restrict-system-libc-headers.Includes
value: "arpa/inet.h,assert.h,ctype.h,errno.h,fcntl.h,getopt.h,libconfig.h,linux/netdevice.h,math.h,netdb.h,netinet/in.h,opus.h,pthread.h,signal.h,sodium/crypto_scalarmult_curve25519.h,sodium.h,sodium/randombytes.h,stdio.h,stdlib.h,string.h,sys/ioctl.h,syslog.h,sys/resource.h,sys/socket.h,sys/stat.h,sys/time.h,sys/types.h,time.h,unistd.h,vpx/vp8cx.h,vpx/vp8dx.h,vpx/vpx_decoder.h,vpx/vpx_encoder.h,vpx/vpx_image.h" value: "arpa/inet.h,assert.h,ctype.h,errno.h,fcntl.h,getopt.h,libconfig.h,limits.h,linux/if.h,math.h,netdb.h,netinet/in.h,opus.h,pthread.h,signal.h,sodium/crypto_scalarmult_curve25519.h,sodium.h,sodium/randombytes.h,stdarg.h,stdbool.h,stddef.h,stdint.h,stdio.h,stdlib.h,string.h,sys/ioctl.h,syslog.h,sys/resource.h,sys/socket.h,sys/stat.h,sys/time.h,sys/types.h,time.h,unistd.h,vpx/vp8cx.h,vpx/vp8dx.h,vpx/vpx_decoder.h,vpx/vpx_encoder.h,vpx/vpx_image.h"
- key: hicpp-signed-bitwise.IgnorePositiveIntegerLiterals - key: hicpp-signed-bitwise.IgnorePositiveIntegerLiterals
value: true value: true
- key: concurrency-mt-unsafe.FunctionSet
value: posix
- key: misc-include-cleaner.IgnoreHeaders
value: "pthread.h;stdbool.h;stddef.h;stdint.;stdint.h;stdint...;cstdint;sodium.*;sys/.*;unistd.h;opus.*;vpx.*;attributes.h;tox_struct.h"
- key: readability-function-cognitive-complexity.Threshold
value: 153 # TODO(iphydf): Decrease. tox_new is the highest at the moment.

View File

@@ -1,6 +1,6 @@
#!/bin/bash -eu #!/bin/bash -eu
FUZZ_TARGETS="bootstrap_fuzzer toxsave_fuzzer" FUZZ_TARGETS="bootstrap_fuzz_test toxsave_fuzz_test"
# out of tree build # out of tree build
cd "$WORK" cd "$WORK"

View File

@@ -1,61 +0,0 @@
#!/bin/bash
set -eu
NPROC=$(nproc)
sudo apt-get install -y --no-install-recommends \
libgtest-dev \
libopus-dev \
libsodium-dev \
libvpx-dev \
llvm-14 \
ninja-build
git clone --depth=1 https://github.com/ralight/mallocfail /tmp/mallocfail
cd /tmp/mallocfail # pushd
make
sudo make install
cd - # popd
export CC=clang
export CXX=clang++
sudo install other/docker/coverage/run_mallocfail /usr/local/bin/run_mallocfail
(cd other/proxy && go get && go build)
other/proxy/proxy &
. ".github/scripts/flags-coverage.sh"
cmake -B_build -H. -GNinja \
-DCMAKE_C_FLAGS="$C_FLAGS" \
-DCMAKE_CXX_FLAGS="$CXX_FLAGS" \
-DCMAKE_EXE_LINKER_FLAGS="$LD_FLAGS" \
-DCMAKE_SHARED_LINKER_FLAGS="$LD_FLAGS" \
-DCMAKE_INSTALL_PREFIX:PATH="$PWD/_install" \
-DENABLE_SHARED=OFF \
-DMIN_LOGGER_LEVEL=TRACE \
-DMUST_BUILD_TOXAV=ON \
-DNON_HERMETIC_TESTS=OFF \
-DSTRICT_ABI=ON \
-DTEST_TIMEOUT_SECONDS=120 \
-DUSE_IPV6=OFF \
-DAUTOTEST=ON \
-DPROXY_TEST=ON
cmake --build _build --parallel "$NPROC" --target install -- -k 0
cd _build # pushd
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6 ||
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6
export PYTHONUNBUFFERED=1
run_mallocfail --ctest=2 --jobs=8
cd - # popd
#coveralls \
# --exclude auto_tests \
# --exclude other \
# --exclude testing \
# --gcov-options '\-lp'
bash <(curl -s https://codecov.io/bash) -x "llvm-cov-14 gcov"

View File

@@ -5,10 +5,10 @@
add_ld_flag -Wl,-z,defs add_ld_flag -Wl,-z,defs
# Make compilation error on a warning # Make compilation error on a warning
add_flag -Werror add_flag -Werror -Wno-unsafe-buffer-usage
# Coverage flags. # Coverage flags.
add_flag --coverage add_flag -fprofile-instr-generate -fcoverage-mapping
# Optimisation, but keep stack traces useful. # Optimisation, but keep stack traces useful.
add_c_flag -fno-inline -fno-omit-frame-pointer add_c_flag -fno-inline -fno-omit-frame-pointer

View File

@@ -1,12 +1,15 @@
#!/bin/bash #!/bin/bash
set -exu set -exu -o pipefail
LOCAL="${1:-}" LOCAL="${1:-}"
readarray -t FILES <<<"$(git ls-files)" readarray -t FILES <<<"$(git ls-files)"
tar c "${FILES[@]}" | docker build -f other/bootstrap_daemon/docker/Dockerfile -t toxchat/bootstrap-node - if ! tar c "${FILES[@]}" | docker build -f other/bootstrap_daemon/docker/Dockerfile -t toxchat/bootstrap-node - 2>&1 | tee docker-build.log; then
grep -o "::error.*::[a-f0-9]* /usr/local/bin/tox-bootstrapd" docker-build.log
false
fi
docker tag toxchat/bootstrap-node:latest toxchat/bootstrap-node:"$(other/print-version)" docker tag toxchat/bootstrap-node:latest toxchat/bootstrap-node:"$(other/print-version)"
sudo useradd \ sudo useradd \

View File

@@ -1,86 +0,0 @@
---
_extends: .github
repository:
name: c-toxcore
description: The future of online communications.
homepage: https://tox.chat/
topics: toxcore, network, p2p, security, encryption, cryptography
branches:
- name: "master"
protection:
required_status_checks:
contexts:
- "bazel-dbg"
- "bazel-opt"
- "build-alpine-s390x"
- "build-android"
- "build-autotools"
- "build-compcert"
- "build-macos"
- "build-tcc"
- "build-win32"
- "build-win64"
- "ci/circleci: asan"
- "ci/circleci: bazel-asan"
- "ci/circleci: bazel-msan"
- "ci/circleci: bazel-tsan"
- "ci/circleci: clang-analyze"
- "ci/circleci: clang-tidy"
- "ci/circleci: cpplint"
- "ci/circleci: infer"
- "ci/circleci: static-analysis"
- "ci/circleci: tsan"
- "ci/circleci: ubsan"
- "cimple"
- "cimplefmt"
- "CodeFactor"
- "code-review/reviewable"
- "common / buildifier"
- "coverage-linux"
- "docker-bootstrap-node"
- "docker-bootstrap-node-websocket"
- "docker-clusterfuzz"
- "docker-esp32"
- "docker-fuzzer"
- "docker-toxcore-js"
- "docker-win32"
- "docker-win64"
- "doxygen"
- "freebsd"
- "Hound"
- "misra"
- "mypy"
- "program-analysis"
- "sonar-scan"
- "tokstyle"
- "TokTok.c-toxcore"
- "TokTok.c-toxcore (windows_msvc_conan shared)"
- "TokTok.c-toxcore (windows_msvc_conan static)"
# Labels specific to c-toxcore.
labels:
- name: "bootstrap"
color: "#01707f"
description: "Bootstrap"
- name: "crypto"
color: "#1d76db"
description: "Crypto"
- name: "file transfers"
color: "#e02abf"
description: "File Transfers"
- name: "messenger"
color: "#d93f0b"
description: "Messenger"
- name: "network"
color: "#d4c5f9"
description: "Network"
- name: "toxav"
color: "#0052cc"
description: "Audio/video"

View File

@@ -13,7 +13,10 @@ jobs:
common: common:
uses: TokTok/ci-tools/.github/workflows/common-ci.yml@master uses: TokTok/ci-tools/.github/workflows/common-ci.yml@master
cppcheck: analysis:
strategy:
matrix:
tool: [autotools, clang-tidy, compcert, cppcheck, doxygen, infer, misra, tcc, tokstyle]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Set up Docker Buildx - name: Set up Docker Buildx
@@ -21,84 +24,16 @@ jobs:
- name: Docker Build - name: Docker Build
uses: docker/build-push-action@v4 uses: docker/build-push-action@v4
with: with:
file: other/docker/cppcheck/Dockerfile file: other/docker/${{ matrix.tool }}/Dockerfile
mypy: coverage-linux:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- name: Set up Python 3.9 - name: Build, test, and upload coverage
uses: actions/setup-python@v1 run: other/docker/coverage/run
with:
python-version: 3.9
- name: Install mypy
run: pip install mypy
- name: Run mypy
run: |
(find . -name "*.py" -and -not -name "conanfile.py"; grep -lR '^#!.*python') \
| xargs -n1 -P8 mypy --strict
doxygen:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker Build
uses: docker/build-push-action@v4
with:
file: other/docker/doxygen/Dockerfile
tokstyle:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker Build
uses: docker/build-push-action@v4
with:
file: other/docker/tokstyle/Dockerfile
misra:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker Build
uses: docker/build-push-action@v4
with:
file: other/docker/misra/Dockerfile
build-autotools:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker Build
uses: docker/build-push-action@v4
with:
file: other/docker/autotools/Dockerfile
build-tcc:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker Build
uses: docker/build-push-action@v4
with:
file: other/docker/tcc/Dockerfile
build-compcert:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker Build
uses: docker/build-push-action@v4
with:
file: other/docker/compcert/Dockerfile
generate-events: generate-events:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -120,42 +55,6 @@ jobs:
- name: Run cimplefmt - name: Run cimplefmt
run: other/docker/cimplefmt/run -u $(find tox* -name "*.[ch]") run: other/docker/cimplefmt/run -u $(find tox* -name "*.[ch]")
build-win32:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Cross compilation
run: .github/scripts/cmake-win32 script
build-win64:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Cross compilation
run: .github/scripts/cmake-win64 script
build-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Build and test
run: .github/scripts/cmake-osx
coverage-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Build, test, and upload coverage
run: other/docker/coverage/run
build-android: build-android:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -166,3 +65,68 @@ jobs:
- run: .github/scripts/cmake-android arm64-v8a - run: .github/scripts/cmake-android arm64-v8a
- run: .github/scripts/cmake-android x86 - run: .github/scripts/cmake-android x86
- run: .github/scripts/cmake-android x86_64 - run: .github/scripts/cmake-android x86_64
build-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Build and test
run: .github/scripts/cmake-osx
build-msvc:
strategy:
matrix:
version: [2019, 2022]
runs-on: windows-${{ matrix.version }}
env:
VCPKG_ROOT: "C:/vcpkg"
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Export GitHub Actions cache environment variables
uses: actions/github-script@v6
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Configure CMake
run: cmake --preset windows-default
- name: Build
run: cmake --build _build -j $([int]$env:NUMBER_OF_PROCESSORS+2)
- name: Test
run: |
cd _build
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6 --build-config Debug
build-windows:
strategy:
matrix:
bits: [32, 64]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Cross compilation
run: .github/scripts/cmake-win${{ matrix.bits }} script
mypy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: 3.9
- name: Install mypy
run: pip install mypy
- name: Run mypy
run: |
(find . -name "*.py" -and -not -name "conanfile.py"; grep -lR '^#!.*python') \
| xargs -n1 -P8 mypy --strict

View File

@@ -14,6 +14,8 @@ Thumbs.db
/_build /_build
/_install /_install
/tox-0.0.0* /tox-0.0.0*
/.vs
/CppProperties.json
CMakeCache.txt CMakeCache.txt
CMakeFiles CMakeFiles
Makefile Makefile
@@ -68,7 +70,7 @@ build/
*.nvim* *.nvim*
*.vim* *.vim*
#kdevelop # kdevelop
.kdev/ .kdev/
*.kdev* *.kdev*
@@ -91,4 +93,9 @@ cscope.files
# rpm # rpm
tox.spec tox.spec
# clangd
.cache/
compile_commands.json
/infer
.idea/ .idea/

View File

@@ -1,7 +1,7 @@
load("@rules_cc//cc:defs.bzl", "cc_library") load("@rules_cc//cc:defs.bzl", "cc_library")
load("//tools/project:build_defs.bzl", "project") load("//tools/project:build_defs.bzl", "project")
project() project(license = "gpl3-https")
genrule( genrule(
name = "public_headers", name = "public_headers",

View File

@@ -81,7 +81,7 @@ find_package(GTest)
set(CMAKE_MACOSX_RPATH ON) set(CMAKE_MACOSX_RPATH ON)
# Set standard version for compiler. # Set standard version for compiler.
if(MSVC) if(MSVC AND MSVC_TOOLSET_VERSION LESS 143)
# https://developercommunity.visualstudio.com/t/older-winsdk-headers-are-incompatible-with-zcprepr/1593479 # https://developercommunity.visualstudio.com/t/older-winsdk-headers-are-incompatible-with-zcprepr/1593479
set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD 99)
else() else()
@@ -94,6 +94,35 @@ set(CMAKE_CXX_EXTENSIONS OFF)
message(STATUS "Supported C compiler features = ${CMAKE_C_COMPILE_FEATURES}") message(STATUS "Supported C compiler features = ${CMAKE_C_COMPILE_FEATURES}")
message(STATUS "Supported C++ compiler features = ${CMAKE_CXX_COMPILE_FEATURES}") message(STATUS "Supported C++ compiler features = ${CMAKE_CXX_COMPILE_FEATURES}")
# Enable some warnings if we know the compiler.
if(MSVC)
add_compile_options(/W4 /analyze)
add_compile_options(/wd4100) # unreferenced formal parameter
add_compile_options(/wd4267) # narrowing conversion
add_compile_options(/wd4244) # narrowing conversion
add_compile_options(/wd4127) # conditional expression is constant
add_compile_options(/wd4995) # #pragma deprecated
add_compile_options(/wd4018) # signed/unsigned compare
add_compile_options(/wd4310) # cast truncates constant value
add_compile_options(/wd4389) # signed/unsigned compare
add_compile_options(/wd4245) # signed/unsigned assign/return/function call
add_compile_options(/wd4200) # nonstandard extension used: zero-sized array in struct/union
add_compile_options(/wd4702) # unreachable code
add_compile_options(/wd6340) # unsigned int passed to signed parameter
add_compile_options(/wd6326) # potential comparison of a constant with another constant
# TODO(iphydf): Look into these
add_compile_options(/wd4996) # use WSAAddressToStringW() instead of WSAAddressToStringA()
add_compile_options(/wd6255) # don't use alloca
add_compile_options(/wd6385) # reading invalid data
add_compile_options(/wd6001) # using uninitialized memory
add_compile_options(/wd6101) # returning uninitialized memory
add_compile_options(/wd6386) # buffer overrun
add_compile_options(/wd6011) # NULL dereference
add_compile_options(/wd6031) # sscanf return value ignored
add_compile_options(/wd6387) # passing NULL to fwrite
endif()
set(MIN_LOGGER_LEVEL "" CACHE STRING "Logging level to use (TRACE, DEBUG, INFO, WARNING, ERROR)") set(MIN_LOGGER_LEVEL "" CACHE STRING "Logging level to use (TRACE, DEBUG, INFO, WARNING, ERROR)")
if(MIN_LOGGER_LEVEL) if(MIN_LOGGER_LEVEL)
if(("${MIN_LOGGER_LEVEL}" STREQUAL "TRACE") OR if(("${MIN_LOGGER_LEVEL}" STREQUAL "TRACE") OR
@@ -131,21 +160,7 @@ if(BOOTSTRAP_DAEMON AND WIN32)
set(BOOTSTRAP_DAEMON OFF) set(BOOTSTRAP_DAEMON OFF)
endif() endif()
# Enabling this breaks all other tests and no network connections will be possible
option(BUILD_FUZZ_TESTS "Build fuzzing harnesses" OFF) option(BUILD_FUZZ_TESTS "Build fuzzing harnesses" OFF)
if(BUILD_FUZZ_TESTS)
message(STATUS "Building in fuzz testing mode, no network connection will be possible")
# Disable everything we can
set(AUTOTEST OFF)
set(BUILD_MISC_TESTS OFF)
set(BUILD_FUN_UTILS OFF)
set(ENABLE_SHARED OFF)
set(MUST_BUILD_TOXAV OFF)
set(BUILD_TOXAV OFF)
set(BOOTSTRAP_DAEMON OFF)
set(DHT_BOOTSTRAP OFF)
endif()
if(MSVC) if(MSVC)
option(MSVC_STATIC_SODIUM "Whether to link libsodium statically for MSVC" OFF) option(MSVC_STATIC_SODIUM "Whether to link libsodium statically for MSVC" OFF)
@@ -323,14 +338,20 @@ set(toxcore_SOURCES
toxcore/tox.h toxcore/tox.h
toxcore/tox_private.c toxcore/tox_private.c
toxcore/tox_private.h toxcore/tox_private.h
toxcore/tox_pack.c
toxcore/tox_pack.h
toxcore/tox_unpack.c toxcore/tox_unpack.c
toxcore/tox_unpack.h toxcore/tox_unpack.h
toxcore/util.c toxcore/util.c
toxcore/util.h) toxcore/util.h)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} ${LIBSODIUM_LIBRARIES}) if(TARGET unofficial-sodium::sodium)
set(toxcore_LINK_DIRECTORIES ${toxcore_LINK_DIRECTORIES} ${LIBSODIUM_LIBRARY_DIRS}) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} unofficial-sodium::sodium)
set(toxcore_INCLUDE_DIRECTORIES ${toxcore_INCLUDE_DIRECTORIES} ${LIBSODIUM_INCLUDE_DIRS}) else()
set(toxcore_COMPILE_OPTIONS ${toxcore_COMPILE_OPTIONS} ${LIBSODIUM_CFLAGS_OTHER}) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} ${LIBSODIUM_LIBRARIES})
set(toxcore_LINK_DIRECTORIES ${toxcore_LINK_DIRECTORIES} ${LIBSODIUM_LIBRARY_DIRS})
set(toxcore_INCLUDE_DIRECTORIES ${toxcore_INCLUDE_DIRECTORIES} ${LIBSODIUM_INCLUDE_DIRS})
set(toxcore_COMPILE_OPTIONS ${toxcore_COMPILE_OPTIONS} ${LIBSODIUM_CFLAGS_OTHER})
endif()
set(toxcore_PKGCONFIG_REQUIRES ${toxcore_PKGCONFIG_REQUIRES} libsodium) set(toxcore_PKGCONFIG_REQUIRES ${toxcore_PKGCONFIG_REQUIRES} libsodium)
set(toxcore_API_HEADERS set(toxcore_API_HEADERS
${toxcore_SOURCE_DIR}/toxcore/tox.h^tox ${toxcore_SOURCE_DIR}/toxcore/tox.h^tox
@@ -366,10 +387,14 @@ if(BUILD_TOXAV)
set(toxcore_API_HEADERS ${toxcore_API_HEADERS} set(toxcore_API_HEADERS ${toxcore_API_HEADERS}
${toxcore_SOURCE_DIR}/toxav/toxav.h^toxav) ${toxcore_SOURCE_DIR}/toxav/toxav.h^toxav)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} ${OPUS_LIBRARIES} ${VPX_LIBRARIES}) if(MSVC)
set(toxcore_LINK_DIRECTORIES ${toxcore_LINK_DIRECTORIES} ${OPUS_LIBRARY_DIRS} ${VPX_LIBRARY_DIRS}) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} PkgConfig::OPUS PkgConfig::VPX)
set(toxcore_INCLUDE_DIRECTORIES ${toxcore_INCLUDE_DIRECTORIES} ${OPUS_INCLUDE_DIRS} ${VPX_INCLUDE_DIRS}) else()
set(toxcore_COMPILE_OPTIONS ${toxcore_COMPILE_OPTIONS} ${OPUS_CFLAGS_OTHER} ${VPX_CFLAGS_OTHER}) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} ${OPUS_LIBRARIES} ${VPX_LIBRARIES})
set(toxcore_LINK_DIRECTORIES ${toxcore_LINK_DIRECTORIES} ${OPUS_LIBRARY_DIRS} ${VPX_LIBRARY_DIRS})
set(toxcore_INCLUDE_DIRECTORIES ${toxcore_INCLUDE_DIRECTORIES} ${OPUS_INCLUDE_DIRS} ${VPX_INCLUDE_DIRS})
set(toxcore_COMPILE_OPTIONS ${toxcore_COMPILE_OPTIONS} ${OPUS_CFLAGS_OTHER} ${VPX_CFLAGS_OTHER})
endif()
set(toxcore_PKGCONFIG_REQUIRES ${toxcore_PKGCONFIG_REQUIRES} opus vpx) set(toxcore_PKGCONFIG_REQUIRES ${toxcore_PKGCONFIG_REQUIRES} opus vpx)
endif() endif()
@@ -400,7 +425,6 @@ if(CMAKE_THREAD_LIBS_INIT)
set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} ${CMAKE_THREAD_LIBS_INIT})
endif() endif()
if(NSL_LIBRARIES) if(NSL_LIBRARIES)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} ${NSL_LIBRARIES}) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} ${NSL_LIBRARIES})
set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} -lnsl) set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} -lnsl)
@@ -416,9 +440,13 @@ if(SOCKET_LIBRARIES)
set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} -lsocket) set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} -lsocket)
endif() endif()
if(TARGET PThreads4W::PThreads4W)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} PThreads4W::PThreads4W)
elseif(TARGET Threads::Threads)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} Threads::Threads)
endif()
if(WIN32) if(WIN32)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} ws2_32 iphlpapi) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} iphlpapi wsock32 ws2_32)
set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} -lws2_32 -liphlpapi)
endif() endif()
################################################################################ ################################################################################
@@ -428,20 +456,33 @@ endif()
################################################################################ ################################################################################
# Create combined library from all the sources. # Create combined library from all the sources.
add_module(toxcore ${toxcore_SOURCES}) if(ENABLE_SHARED)
add_library(toxcore_shared SHARED ${toxcore_SOURCES})
set_target_properties(toxcore_shared PROPERTIES OUTPUT_NAME toxcore)
target_link_libraries(toxcore_shared PRIVATE ${toxcore_LINK_LIBRARIES})
target_link_directories(toxcore_shared PUBLIC ${toxcore_LINK_DIRECTORIES})
target_include_directories(toxcore_shared SYSTEM PRIVATE ${toxcore_INCLUDE_DIRECTORIES})
target_compile_options(toxcore_shared PRIVATE ${toxcore_COMPILE_OPTIONS})
endif()
# Link it to all dependencies. if(ENABLE_STATIC)
if(TARGET toxcore_static) add_library(toxcore_static STATIC ${toxcore_SOURCES})
if(NOT MSVC)
set_target_properties(toxcore_static PROPERTIES OUTPUT_NAME toxcore)
endif()
target_link_libraries(toxcore_static PRIVATE ${toxcore_LINK_LIBRARIES}) target_link_libraries(toxcore_static PRIVATE ${toxcore_LINK_LIBRARIES})
target_link_directories(toxcore_static PUBLIC ${toxcore_LINK_DIRECTORIES}) target_link_directories(toxcore_static PUBLIC ${toxcore_LINK_DIRECTORIES})
target_include_directories(toxcore_static SYSTEM PRIVATE ${toxcore_INCLUDE_DIRECTORIES}) target_include_directories(toxcore_static SYSTEM PRIVATE ${toxcore_INCLUDE_DIRECTORIES})
target_compile_options(toxcore_static PRIVATE ${toxcore_COMPILE_OPTIONS}) target_compile_options(toxcore_static PRIVATE ${toxcore_COMPILE_OPTIONS})
endif() endif()
if(TARGET toxcore_shared)
target_link_libraries(toxcore_shared PRIVATE ${toxcore_LINK_LIBRARIES}) if(BUILD_FUZZ_TESTS)
target_link_directories(toxcore_shared PUBLIC ${toxcore_LINK_DIRECTORIES}) add_library(toxcore_fuzz STATIC ${toxcore_SOURCES})
target_include_directories(toxcore_shared SYSTEM PRIVATE ${toxcore_INCLUDE_DIRECTORIES}) target_link_libraries(toxcore_fuzz PRIVATE ${toxcore_LINK_LIBRARIES})
target_compile_options(toxcore_shared PRIVATE ${toxcore_COMPILE_OPTIONS}) target_link_directories(toxcore_fuzz PUBLIC ${toxcore_LINK_DIRECTORIES})
target_include_directories(toxcore_fuzz SYSTEM PRIVATE ${toxcore_INCLUDE_DIRECTORIES})
target_compile_options(toxcore_fuzz PRIVATE ${toxcore_COMPILE_OPTIONS})
target_compile_definitions(toxcore_fuzz PUBLIC "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION")
endif() endif()
# Make version script (on systems that support it) to limit symbol visibility. # Make version script (on systems that support it) to limit symbol visibility.
@@ -457,14 +498,27 @@ install_module(toxcore DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tox)
# #
################################################################################ ################################################################################
add_library(test_util STATIC
toxcore/DHT_test_util.cc
toxcore/DHT_test_util.hh
toxcore/crypto_core_test_util.cc
toxcore/crypto_core_test_util.hh
toxcore/mem_test_util.cc
toxcore/mem_test_util.hh
toxcore/network_test_util.cc
toxcore/network_test_util.hh
toxcore/test_util.cc
toxcore/test_util.hh)
function(unit_test subdir target) function(unit_test subdir target)
add_executable(unit_${target}_test ${subdir}/${target}_test.cc) add_executable(unit_${target}_test ${subdir}/${target}_test.cc)
target_link_libraries(unit_${target}_test PRIVATE test_util)
if(TARGET toxcore_static) if(TARGET toxcore_static)
target_link_libraries(unit_${target}_test PRIVATE toxcore_static) target_link_libraries(unit_${target}_test PRIVATE toxcore_static)
else() else()
target_link_libraries(unit_${target}_test PRIVATE toxcore_shared) target_link_libraries(unit_${target}_test PRIVATE toxcore_shared)
endif() endif()
target_link_libraries(unit_${target}_test PRIVATE GTest::GTest GTest::Main) target_link_libraries(unit_${target}_test PRIVATE GTest::gtest GTest::gtest_main GTest::gmock)
set_target_properties(unit_${target}_test PROPERTIES COMPILE_FLAGS "${TEST_CXX_FLAGS}") set_target_properties(unit_${target}_test PROPERTIES COMPILE_FLAGS "${TEST_CXX_FLAGS}")
add_test(NAME ${target} COMMAND ${CROSSCOMPILING_EMULATOR} unit_${target}_test) add_test(NAME ${target} COMMAND ${CROSSCOMPILING_EMULATOR} unit_${target}_test)
set_property(TEST ${target} PROPERTY ENVIRONMENT "LLVM_PROFILE_FILE=${target}.profraw") set_property(TEST ${target} PROPERTY ENVIRONMENT "LLVM_PROFILE_FILE=${target}.profraw")
@@ -484,6 +538,7 @@ if(GTEST_FOUND)
unit_test(toxcore mem) unit_test(toxcore mem)
unit_test(toxcore mono_time) unit_test(toxcore mono_time)
unit_test(toxcore ping_array) unit_test(toxcore ping_array)
unit_test(toxcore test_util)
unit_test(toxcore tox) unit_test(toxcore tox)
unit_test(toxcore util) unit_test(toxcore util)
endif() endif()
@@ -516,6 +571,14 @@ if(DHT_BOOTSTRAP)
target_link_libraries(DHT_bootstrap PRIVATE toxcore_shared) target_link_libraries(DHT_bootstrap PRIVATE toxcore_shared)
endif() endif()
target_link_libraries(DHT_bootstrap PRIVATE misc_tools) target_link_libraries(DHT_bootstrap PRIVATE misc_tools)
if(TARGET unofficial-sodium::sodium)
target_link_libraries(DHT_bootstrap PRIVATE unofficial-sodium::sodium)
endif()
if(TARGET PThreads4W::PThreads4W)
target_link_libraries(DHT_bootstrap PRIVATE PThreads4W::PThreads4W)
elseif(TARGET Threads::Threads)
target_link_libraries(DHT_bootstrap PRIVATE Threads::Threads)
endif()
install(TARGETS DHT_bootstrap RUNTIME DESTINATION bin) install(TARGETS DHT_bootstrap RUNTIME DESTINATION bin)
endif() endif()

View File

@@ -0,0 +1,21 @@
{
"version": 3,
"configurePresets": [
{
"name": "windows-default",
"binaryDir": "${sourceDir}/_build",
"cacheVariables": {
"ENABLE_SHARED": true,
"ENABLE_STATIC": true,
"AUTOTEST": true,
"BUILD_MISC_TESTS": true,
"BOOTSTRAP_DAEMON": false,
"MUST_BUILD_TOXAV": true,
"TEST_TIMEOUT_SECONDS": "60",
"CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS": true,
"CMAKE_COMPILE_WARNING_AS_ERROR": true,
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
}
}
]
}

View File

@@ -1,7 +1,7 @@
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007 Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
@@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail. Also add information on how to contact you by electronic and paper mail.
@@ -664,12 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school, You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>. <https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>. <https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -9,6 +9,11 @@ if(TARGET toxcore_static)
else() else()
target_link_libraries(auto_test_support PRIVATE toxcore_shared) target_link_libraries(auto_test_support PRIVATE toxcore_shared)
endif() endif()
if(TARGET PThreads4W::PThreads4W)
target_link_libraries(auto_test_support PRIVATE PThreads4W::PThreads4W)
elseif(TARGET Threads::Threads)
target_link_libraries(auto_test_support PRIVATE Threads::Threads)
endif()
function(auto_test target) function(auto_test target)
add_executable(auto_${target}_test ${target}_test.c) add_executable(auto_${target}_test ${target}_test.c)
@@ -18,12 +23,15 @@ function(auto_test target)
else() else()
target_link_libraries(auto_${target}_test PRIVATE toxcore_shared) target_link_libraries(auto_${target}_test PRIVATE toxcore_shared)
endif() endif()
if(NOT ARGV1 STREQUAL "DONT_RUN") if(TARGET PThreads4W::PThreads4W)
add_test(NAME ${target} COMMAND ${CROSSCOMPILING_EMULATOR} auto_${target}_test) target_link_libraries(auto_${target}_test PRIVATE PThreads4W::PThreads4W)
set_tests_properties(${target} PROPERTIES TIMEOUT "${TEST_TIMEOUT_SECONDS}") elseif(TARGET Threads::Threads)
# add the source dir as environment variable, so the testdata can be found target_link_libraries(auto_${target}_test PRIVATE Threads::Threads)
set_tests_properties(${target} PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=${target}.profraw;srcdir=${CMAKE_CURRENT_SOURCE_DIR}")
endif() endif()
add_test(NAME ${target} COMMAND ${CROSSCOMPILING_EMULATOR} auto_${target}_test)
set_tests_properties(${target} PROPERTIES TIMEOUT "${TEST_TIMEOUT_SECONDS}")
# add the source dir as environment variable, so the testdata can be found
set_tests_properties(${target} PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=${target}.profraw;srcdir=${CMAKE_CURRENT_SOURCE_DIR}")
endfunction() endfunction()
auto_test(TCP) auto_test(TCP)
@@ -38,8 +46,9 @@ auto_test(crypto)
#auto_test(dht) # Doesn't work with UNITY_BUILD. #auto_test(dht) # Doesn't work with UNITY_BUILD.
auto_test(dht_getnodes_api) auto_test(dht_getnodes_api)
auto_test(encryptsave) auto_test(encryptsave)
auto_test(file_transfer)
auto_test(file_saving) auto_test(file_saving)
auto_test(file_streaming)
auto_test(file_transfer)
auto_test(forwarding) auto_test(forwarding)
auto_test(friend_connection) auto_test(friend_connection)
auto_test(friend_request) auto_test(friend_request)
@@ -89,15 +98,20 @@ if(BUILD_TOXAV)
auto_test(toxav_basic) auto_test(toxav_basic)
auto_test(toxav_many) auto_test(toxav_many)
target_link_libraries(auto_toxav_basic_test PRIVATE ${VPX_LIBRARIES}) if(MSVC)
target_link_directories(auto_toxav_basic_test PRIVATE ${VPX_LIBRARY_DIRS}) target_link_libraries(auto_toxav_basic_test PRIVATE PkgConfig::VPX)
target_include_directories(auto_toxav_basic_test SYSTEM PRIVATE ${VPX_INCLUDE_DIRS}) target_link_libraries(auto_toxav_many_test PRIVATE PkgConfig::VPX)
target_compile_options(auto_toxav_basic_test PRIVATE ${VPX_CFLAGS_OTHER}) else()
target_link_libraries(auto_toxav_basic_test PRIVATE ${VPX_LIBRARIES})
target_link_directories(auto_toxav_basic_test PRIVATE ${VPX_LIBRARY_DIRS})
target_include_directories(auto_toxav_basic_test SYSTEM PRIVATE ${VPX_INCLUDE_DIRS})
target_compile_options(auto_toxav_basic_test PRIVATE ${VPX_CFLAGS_OTHER})
target_link_libraries(auto_toxav_many_test PRIVATE ${VPX_LIBRARIES}) target_link_libraries(auto_toxav_many_test PRIVATE ${VPX_LIBRARIES})
target_link_directories(auto_toxav_many_test PRIVATE ${VPX_LIBRARY_DIRS}) target_link_directories(auto_toxav_many_test PRIVATE ${VPX_LIBRARY_DIRS})
target_include_directories(auto_toxav_many_test SYSTEM PRIVATE ${VPX_INCLUDE_DIRS}) target_include_directories(auto_toxav_many_test SYSTEM PRIVATE ${VPX_INCLUDE_DIRS})
target_compile_options(auto_toxav_many_test PRIVATE ${VPX_CFLAGS_OTHER}) target_compile_options(auto_toxav_many_test PRIVATE ${VPX_CFLAGS_OTHER})
endif()
endif() endif()
if(PROXY_TEST) if(PROXY_TEST)

View File

@@ -15,6 +15,7 @@ TESTS = \
crypto_test \ crypto_test \
encryptsave_test \ encryptsave_test \
file_saving_test \ file_saving_test \
file_streaming_test \
file_transfer_test \ file_transfer_test \
forwarding_test \ forwarding_test \
friend_connection_test \ friend_connection_test \
@@ -103,6 +104,10 @@ file_saving_test_SOURCES = ../auto_tests/file_saving_test.c
file_saving_test_CFLAGS = $(AUTOTEST_CFLAGS) file_saving_test_CFLAGS = $(AUTOTEST_CFLAGS)
file_saving_test_LDADD = $(AUTOTEST_LDADD) file_saving_test_LDADD = $(AUTOTEST_LDADD)
file_streaming_test_SOURCES = ../auto_tests/file_streaming_test.c
file_streaming_test_CFLAGS = $(AUTOTEST_CFLAGS)
file_streaming_test_LDADD = $(AUTOTEST_LDADD)
file_transfer_test_SOURCES = ../auto_tests/file_transfer_test.c file_transfer_test_SOURCES = ../auto_tests/file_transfer_test.c
file_transfer_test_CFLAGS = $(AUTOTEST_CFLAGS) file_transfer_test_CFLAGS = $(AUTOTEST_CFLAGS)
file_transfer_test_LDADD = $(AUTOTEST_LDADD) file_transfer_test_LDADD = $(AUTOTEST_LDADD)
@@ -187,14 +192,14 @@ TCP_test_SOURCES = ../auto_tests/TCP_test.c
TCP_test_CFLAGS = $(AUTOTEST_CFLAGS) TCP_test_CFLAGS = $(AUTOTEST_CFLAGS)
TCP_test_LDADD = $(AUTOTEST_LDADD) TCP_test_LDADD = $(AUTOTEST_LDADD)
tox_events_test_SOURCES = ../auto_tests/tox_events_test.c
tox_events_test_CFLAGS = $(AUTOTEST_CFLAGS)
tox_events_test_LDADD = $(AUTOTEST_LDADD)
tox_dispatch_test_SOURCES = ../auto_tests/tox_dispatch_test.c tox_dispatch_test_SOURCES = ../auto_tests/tox_dispatch_test.c
tox_dispatch_test_CFLAGS = $(AUTOTEST_CFLAGS) tox_dispatch_test_CFLAGS = $(AUTOTEST_CFLAGS)
tox_dispatch_test_LDADD = $(AUTOTEST_LDADD) tox_dispatch_test_LDADD = $(AUTOTEST_LDADD)
tox_events_test_SOURCES = ../auto_tests/tox_events_test.c
tox_events_test_CFLAGS = $(AUTOTEST_CFLAGS)
tox_events_test_LDADD = $(AUTOTEST_LDADD)
tox_many_tcp_test_SOURCES = ../auto_tests/tox_many_tcp_test.c tox_many_tcp_test_SOURCES = ../auto_tests/tox_many_tcp_test.c
tox_many_tcp_test_CFLAGS = $(AUTOTEST_CFLAGS) tox_many_tcp_test_CFLAGS = $(AUTOTEST_CFLAGS)
tox_many_tcp_test_LDADD = $(AUTOTEST_LDADD) tox_many_tcp_test_LDADD = $(AUTOTEST_LDADD)

View File

@@ -13,6 +13,10 @@
#define ABORT_ON_LOG_ERROR true #define ABORT_ON_LOG_ERROR true
#endif #endif
#ifndef USE_IPV6
#define USE_IPV6 1
#endif
Run_Auto_Options default_run_auto_options(void) Run_Auto_Options default_run_auto_options(void)
{ {
return (Run_Auto_Options) { return (Run_Auto_Options) {
@@ -149,6 +153,8 @@ void set_mono_time_callback(AutoTox *autotox)
Mono_Time *mono_time = autotox->tox->mono_time; Mono_Time *mono_time = autotox->tox->mono_time;
autotox->clock = current_time_monotonic(mono_time); autotox->clock = current_time_monotonic(mono_time);
ck_assert_msg(autotox->clock >= 1000,
"clock is too low (not initialised?): %lu", (unsigned long)autotox->clock);
mono_time_set_current_time_callback(mono_time, nullptr, nullptr); // set to default first mono_time_set_current_time_callback(mono_time, nullptr, nullptr); // set to default first
mono_time_set_current_time_callback(mono_time, get_state_clock_callback, &autotox->clock); mono_time_set_current_time_callback(mono_time, get_state_clock_callback, &autotox->clock);
} }
@@ -191,6 +197,7 @@ void reload(AutoTox *autotox)
struct Tox_Options *const options = tox_options_new(nullptr); struct Tox_Options *const options = tox_options_new(nullptr);
ck_assert(options != nullptr); ck_assert(options != nullptr);
tox_options_set_ipv6_enabled(options, USE_IPV6);
tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
tox_options_set_savedata_data(options, autotox->save_state, autotox->save_size); tox_options_set_savedata_data(options, autotox->save_state, autotox->save_size);
autotox->tox = tox_new_log(options, nullptr, &autotox->index); autotox->tox = tox_new_log(options, nullptr, &autotox->index);
@@ -212,6 +219,8 @@ static void initialise_autotox(struct Tox_Options *options, AutoTox *autotox, ui
struct Tox_Options *default_opts = tox_options_new(nullptr); struct Tox_Options *default_opts = tox_options_new(nullptr);
ck_assert(default_opts != nullptr); ck_assert(default_opts != nullptr);
tox_options_set_ipv6_enabled(default_opts, USE_IPV6);
if (options == nullptr) { if (options == nullptr) {
options = default_opts; options = default_opts;
} }
@@ -424,6 +433,7 @@ Tox *tox_new_log_lan(struct Tox_Options *options, Tox_Err_New *err, void *log_us
assert(log_options != nullptr); assert(log_options != nullptr);
tox_options_set_ipv6_enabled(log_options, USE_IPV6);
tox_options_set_local_discovery_enabled(log_options, lan_discovery); tox_options_set_local_discovery_enabled(log_options, lan_discovery);
// Use a higher start port for non-LAN-discovery tests so it's more likely for the LAN discovery // Use a higher start port for non-LAN-discovery tests so it's more likely for the LAN discovery
// test to get the default port 33445. // test to get the default port 33445.

View File

@@ -9,7 +9,7 @@
#define ck_assert(ok) do { \ #define ck_assert(ok) do { \
if (!(ok)) { \ if (!(ok)) { \
fprintf(stderr, "%s:%d: failed `%s'\n", __FILE__, __LINE__, #ok); \ fprintf(stderr, "%s:%d: failed `%s'\n", __FILE__, __LINE__, #ok); \
abort(); \ exit(7); \
} \ } \
} while (0) } while (0)
@@ -18,7 +18,7 @@
fprintf(stderr, "%s:%d: failed `%s': ", __FILE__, __LINE__, #ok); \ fprintf(stderr, "%s:%d: failed `%s': ", __FILE__, __LINE__, #ok); \
fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \ fprintf(stderr, "\n"); \
abort(); \ exit(7); \
} \ } \
} while (0) } while (0)
@@ -26,7 +26,7 @@
fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); \ fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \ fprintf(stderr, "\n"); \
abort(); \ exit(7); \
} while (0) } while (0)
#endif // C_TOXCORE_AUTO_TESTS_CHECK_COMPAT_H #endif // C_TOXCORE_AUTO_TESTS_CHECK_COMPAT_H

View File

@@ -0,0 +1,275 @@
/* File transfer test: streaming version (no known size).
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "../testing/misc_tools.h"
#include "../toxcore/ccompat.h"
#include "../toxcore/tox.h"
#include "../toxcore/util.h"
#include "auto_test_support.h"
#include "check_compat.h"
#ifndef USE_IPV6
#define USE_IPV6 1
#endif
#ifdef TOX_LOCALHOST
#undef TOX_LOCALHOST
#endif
#if USE_IPV6
#define TOX_LOCALHOST "::1"
#else
#define TOX_LOCALHOST "127.0.0.1"
#endif
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
{
if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
tox_friend_add_norequest(m, public_key, nullptr);
}
}
static uint64_t size_recv;
static uint64_t sending_pos;
static uint8_t file_cmp_id[TOX_FILE_ID_LENGTH];
static uint32_t file_accepted;
static uint64_t file_size;
static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, uint64_t filesize,
const uint8_t *filename, size_t filename_length, void *userdata)
{
ck_assert_msg(kind == TOX_FILE_KIND_DATA, "bad kind");
ck_assert_msg(filename_length == sizeof("Gentoo.exe")
&& memcmp(filename, "Gentoo.exe", sizeof("Gentoo.exe")) == 0, "bad filename");
uint8_t file_id[TOX_FILE_ID_LENGTH];
ck_assert_msg(tox_file_get_file_id(tox, friend_number, file_number, file_id, nullptr), "tox_file_get_file_id error");
ck_assert_msg(memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) == 0, "bad file_id");
uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
ck_assert_msg(memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) != 0, "empty file_id");
file_size = filesize;
if (filesize) {
sending_pos = size_recv = 1337;
Tox_Err_File_Seek err_s;
ck_assert_msg(tox_file_seek(tox, friend_number, file_number, 1337, &err_s), "tox_file_seek error");
ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_OK, "tox_file_seek wrong error");
} else {
sending_pos = size_recv = 0;
}
Tox_Err_File_Control error;
ck_assert_msg(tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error),
"tox_file_control failed. %i", error);
++file_accepted;
Tox_Err_File_Seek err_s;
ck_assert_msg(!tox_file_seek(tox, friend_number, file_number, 1234, &err_s), "tox_file_seek no error");
ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_DENIED, "tox_file_seek wrong error");
}
static uint32_t sendf_ok;
static void file_print_control(Tox *tox, uint32_t friend_number, uint32_t file_number, Tox_File_Control control,
void *userdata)
{
/* First send file num is 0.*/
if (file_number == 0 && control == TOX_FILE_CONTROL_RESUME) {
sendf_ok = 1;
}
}
static uint64_t max_sending;
static bool m_send_reached;
static uint8_t sending_num;
static bool file_sending_done;
static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
size_t length, void *user_data)
{
ck_assert_msg(sendf_ok, "didn't get resume control");
ck_assert_msg(sending_pos == position, "bad position %lu", (unsigned long)position);
if (length == 0) {
ck_assert_msg(!file_sending_done, "file sending already done");
file_sending_done = 1;
return;
}
if (position + length > max_sending) {
ck_assert_msg(!m_send_reached, "requested done file transfer");
length = max_sending - position;
m_send_reached = 1;
}
VLA(uint8_t, f_data, length);
memset(f_data, sending_num, length);
Tox_Err_File_Send_Chunk error;
tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error);
ck_assert_msg(error == TOX_ERR_FILE_SEND_CHUNK_OK,
"could not send chunk, error num=%d pos=%d len=%d", (int)error, (int)position, (int)length);
++sending_num;
sending_pos += length;
}
static uint8_t num;
static bool file_recv;
static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
size_t length, void *user_data)
{
ck_assert_msg(size_recv == position, "bad position");
if (length == 0) {
file_recv = 1;
return;
}
VLA(uint8_t, f_data, length);
memset(f_data, num, length);
++num;
ck_assert_msg(memcmp(f_data, data, length) == 0, "FILE_CORRUPTED");
size_recv += length;
}
static void file_transfer_test(void)
{
printf("Starting test: few_clients\n");
uint32_t index[] = { 1, 2, 3 };
long long unsigned int cur_time = time(nullptr);
Tox_Err_New t_n_error;
Tox *tox1 = tox_new_log(nullptr, &t_n_error, &index[0]);
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error");
Tox *tox2 = tox_new_log(nullptr, &t_n_error, &index[1]);
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error");
Tox *tox3 = tox_new_log(nullptr, &t_n_error, &index[2]);
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error");
ck_assert_msg(tox1 && tox2 && tox3, "Failed to create 3 tox instances");
tox_callback_friend_request(tox2, accept_friend_request);
uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(tox2, address);
uint32_t test = tox_friend_add(tox3, address, (const uint8_t *)"Gentoo", 7, nullptr);
ck_assert_msg(test == 0, "Failed to add friend error code: %u", test);
uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
tox_self_get_dht_id(tox1, dht_key);
uint16_t dht_port = tox_self_get_udp_port(tox1, nullptr);
tox_bootstrap(tox2, TOX_LOCALHOST, dht_port, dht_key, nullptr);
tox_bootstrap(tox3, TOX_LOCALHOST, dht_port, dht_key, nullptr);
printf("Waiting for toxes to come online\n");
do {
tox_iterate(tox1, nullptr);
tox_iterate(tox2, nullptr);
tox_iterate(tox3, nullptr);
printf("Connections: self (%d, %d, %d), friends (%d, %d)\n",
tox_self_get_connection_status(tox1),
tox_self_get_connection_status(tox2),
tox_self_get_connection_status(tox3),
tox_friend_get_connection_status(tox2, 0, nullptr),
tox_friend_get_connection_status(tox3, 0, nullptr));
c_sleep(ITERATION_INTERVAL);
} while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE ||
tox_self_get_connection_status(tox3) == TOX_CONNECTION_NONE ||
tox_friend_get_connection_status(tox2, 0, nullptr) == TOX_CONNECTION_NONE ||
tox_friend_get_connection_status(tox3, 0, nullptr) == TOX_CONNECTION_NONE);
printf("Starting file transfer test: 100MiB file.\n");
file_accepted = file_size = sendf_ok = size_recv = 0;
file_recv = 0;
max_sending = UINT64_MAX;
uint64_t totalf_size = 100 * 1024 * 1024;
printf("Starting file streaming transfer test.\n");
file_sending_done = 0;
file_accepted = 0;
file_size = 0;
sendf_ok = 0;
size_recv = 0;
file_recv = 0;
tox_callback_file_recv_chunk(tox3, write_file);
tox_callback_file_recv_control(tox2, file_print_control);
tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
tox_callback_file_recv_control(tox3, file_print_control);
tox_callback_file_recv(tox3, tox_file_receive);
totalf_size = UINT64_MAX;
Tox_File_Number fnum = tox_file_send(
tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr,
(const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr);
ck_assert_msg(fnum != UINT32_MAX, "tox_new_file_sender fail");
Tox_Err_File_Get gfierr;
ck_assert_msg(!tox_file_get_file_id(tox2, 1, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_FRIEND_NOT_FOUND, "wrong error");
ck_assert_msg(!tox_file_get_file_id(tox2, 0, fnum + 1, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_NOT_FOUND, "wrong error");
ck_assert_msg(tox_file_get_file_id(tox2, 0, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id failed");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_OK, "wrong error");
max_sending = 100 * 1024;
m_send_reached = 0;
do {
tox_iterate(tox1, nullptr);
tox_iterate(tox2, nullptr);
tox_iterate(tox3, nullptr);
uint32_t tox1_interval = tox_iteration_interval(tox1);
uint32_t tox2_interval = tox_iteration_interval(tox2);
uint32_t tox3_interval = tox_iteration_interval(tox3);
c_sleep(min_u32(tox1_interval, min_u32(tox2_interval, tox3_interval)));
} while (!file_sending_done);
ck_assert_msg(sendf_ok && file_recv && m_send_reached && totalf_size == file_size && size_recv == max_sending
&& sending_pos == size_recv && file_accepted == 1,
"something went wrong in file transfer %u %u %u %u %u %u %u %lu %lu %lu %lu", sendf_ok, file_recv,
m_send_reached, totalf_size == file_size, size_recv == max_sending, sending_pos == size_recv, file_accepted == 1,
(unsigned long)totalf_size, (unsigned long)file_size,
(unsigned long)size_recv, (unsigned long)sending_pos);
printf("file_transfer_test succeeded, took %llu seconds\n", time(nullptr) - cur_time);
tox_kill(tox1);
tox_kill(tox2);
tox_kill(tox3);
}
int main(void)
{
setvbuf(stdout, nullptr, _IONBF, 0);
file_transfer_test();
return 0;
}

View File

@@ -13,9 +13,14 @@
#include "auto_test_support.h" #include "auto_test_support.h"
#include "check_compat.h" #include "check_compat.h"
/* The Travis-CI container responds poorly to ::1 as a localhost address #ifndef USE_IPV6
* You're encouraged to -D FORCE_TESTS_IPV6 on a local test */ #define USE_IPV6 1
#ifdef FORCE_TESTS_IPV6 #endif
#ifdef TOX_LOCALHOST
#undef TOX_LOCALHOST
#endif
#if USE_IPV6
#define TOX_LOCALHOST "::1" #define TOX_LOCALHOST "::1"
#else #else
#define TOX_LOCALHOST "127.0.0.1" #define TOX_LOCALHOST "127.0.0.1"
@@ -261,53 +266,6 @@ static void file_transfer_test(void)
printf("100MiB file sent in %lu seconds\n", (unsigned long)(time(nullptr) - f_time)); printf("100MiB file sent in %lu seconds\n", (unsigned long)(time(nullptr) - f_time));
printf("Starting file streaming transfer test.\n");
file_sending_done = 0;
file_accepted = 0;
file_size = 0;
sendf_ok = 0;
size_recv = 0;
file_recv = 0;
tox_callback_file_recv_chunk(tox3, write_file);
tox_callback_file_recv_control(tox2, file_print_control);
tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
tox_callback_file_recv_control(tox3, file_print_control);
tox_callback_file_recv(tox3, tox_file_receive);
totalf_size = UINT64_MAX;
fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr,
(const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr);
ck_assert_msg(fnum != UINT32_MAX, "tox_new_file_sender fail");
ck_assert_msg(!tox_file_get_file_id(tox2, 1, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_FRIEND_NOT_FOUND, "wrong error");
ck_assert_msg(!tox_file_get_file_id(tox2, 0, fnum + 1, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_NOT_FOUND, "wrong error");
ck_assert_msg(tox_file_get_file_id(tox2, 0, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id failed");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_OK, "wrong error");
max_sending = 100 * 1024;
m_send_reached = 0;
do {
tox_iterate(tox1, nullptr);
tox_iterate(tox2, nullptr);
tox_iterate(tox3, nullptr);
uint32_t tox1_interval = tox_iteration_interval(tox1);
uint32_t tox2_interval = tox_iteration_interval(tox2);
uint32_t tox3_interval = tox_iteration_interval(tox3);
c_sleep(min_u32(tox1_interval, min_u32(tox2_interval, tox3_interval)));
} while (!file_sending_done);
ck_assert_msg(sendf_ok && file_recv && m_send_reached && totalf_size == file_size && size_recv == max_sending
&& sending_pos == size_recv && file_accepted == 1,
"something went wrong in file transfer %u %u %u %u %u %u %u %lu %lu %lu %lu", sendf_ok, file_recv,
m_send_reached, totalf_size == file_size, size_recv == max_sending, sending_pos == size_recv, file_accepted == 1,
(unsigned long)totalf_size, (unsigned long)file_size,
(unsigned long)size_recv, (unsigned long)sending_pos);
printf("starting file 0 transfer test.\n"); printf("starting file 0 transfer test.\n");
file_sending_done = 0; file_sending_done = 0;

View File

@@ -395,8 +395,9 @@ static void group_message_test(AutoTox *autotoxes)
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
if (state1->peer_joined && !state1->message_sent) { if (state1->peer_joined && !state1->message_sent) {
tox_group_send_message(tox1, group_number, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)TEST_MESSAGE, state1->pseudo_msg_id = tox_group_send_message(
TEST_MESSAGE_LEN, &state1->pseudo_msg_id, &err_send); tox1, group_number, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)TEST_MESSAGE,
TEST_MESSAGE_LEN, &err_send);
ck_assert(err_send == TOX_ERR_GROUP_SEND_MESSAGE_OK); ck_assert(err_send == TOX_ERR_GROUP_SEND_MESSAGE_OK);
state1->message_sent = true; state1->message_sent = true;
} }
@@ -419,7 +420,7 @@ static void group_message_test(AutoTox *autotoxes)
// tox1 sends group a message which should not be seen by tox0's message handler // tox1 sends group a message which should not be seen by tox0's message handler
tox_group_send_message(tox1, group_number, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)IGNORE_MESSAGE, tox_group_send_message(tox1, group_number, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)IGNORE_MESSAGE,
IGNORE_MESSAGE_LEN, nullptr, &err_send); IGNORE_MESSAGE_LEN, &err_send);
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
@@ -506,7 +507,7 @@ static void group_message_test(AutoTox *autotoxes)
memcpy(m + 2, &checksum, sizeof(uint16_t)); memcpy(m + 2, &checksum, sizeof(uint16_t));
tox_group_send_message(tox0, group_number, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)m, message_size, nullptr, &err_send); tox_group_send_message(tox0, group_number, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)m, message_size, &err_send);
ck_assert(err_send == TOX_ERR_GROUP_SEND_MESSAGE_OK); ck_assert(err_send == TOX_ERR_GROUP_SEND_MESSAGE_OK);
} }
@@ -528,7 +529,7 @@ static void group_message_test(AutoTox *autotoxes)
memcpy(m, &i, sizeof(uint16_t)); memcpy(m, &i, sizeof(uint16_t));
tox_group_send_message(tox0, group_number, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)m, 2, nullptr, &err_send); tox_group_send_message(tox0, group_number, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)m, 2, &err_send);
ck_assert(err_send == TOX_ERR_GROUP_SEND_MESSAGE_OK); ck_assert(err_send == TOX_ERR_GROUP_SEND_MESSAGE_OK);
} }

View File

@@ -247,7 +247,7 @@ static void handle_user(State *state, const char *peer_name, size_t peer_name_le
} }
static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t source_peer_id, uint32_t target_peer_id, static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t source_peer_id, uint32_t target_peer_id,
Tox_Group_Mod_Event event, void *user_data) Tox_Group_Mod_Event mod_type, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
@@ -275,7 +275,11 @@ static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t so
Tox_Group_Role role = tox_group_peer_get_role(tox, group_number, target_peer_id, &q_err); Tox_Group_Role role = tox_group_peer_get_role(tox, group_number, target_peer_id, &q_err);
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
switch (event) { fprintf(stderr, "tox%u: got moderator event %d (%s), role = %s\n",
autotox->index, mod_type, tox_group_mod_event_to_string(mod_type),
tox_group_role_to_string(role));
switch (mod_type) {
case TOX_GROUP_MOD_EVENT_MODERATOR: { case TOX_GROUP_MOD_EVENT_MODERATOR: {
handle_mod(state, peer_name, peer_name_len, role); handle_mod(state, peer_name, peer_name_len, role);
break; break;
@@ -298,7 +302,7 @@ static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t so
} }
default: { default: {
ck_assert_msg(0, "Got invalid moderator event %d", event); ck_assert_msg(0, "Got invalid moderator event %d", mod_type);
return; return;
} }
} }
@@ -334,21 +338,21 @@ static void voice_state_message_test(AutoTox *autotox, Tox_Group_Voice_State voi
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
Tox_Err_Group_Send_Message msg_err; Tox_Err_Group_Send_Message msg_err;
bool send_ret = tox_group_send_message(autotox->tox, state->group_number, TOX_MESSAGE_TYPE_NORMAL, tox_group_send_message(autotox->tox, state->group_number, TOX_MESSAGE_TYPE_NORMAL,
(const uint8_t *)"test", 4, nullptr, &msg_err); (const uint8_t *)"test", 4, &msg_err);
switch (self_role) { switch (self_role) {
case TOX_GROUP_ROLE_OBSERVER: { case TOX_GROUP_ROLE_OBSERVER: {
ck_assert(!send_ret && msg_err == TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS); ck_assert(msg_err == TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS);
break; break;
} }
case TOX_GROUP_ROLE_USER: { case TOX_GROUP_ROLE_USER: {
if (voice_state != TOX_GROUP_VOICE_STATE_ALL) { if (voice_state != TOX_GROUP_VOICE_STATE_ALL) {
ck_assert_msg(!send_ret && msg_err == TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS, ck_assert_msg(msg_err == TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS,
"%d, %d", send_ret, msg_err); "%d", msg_err);
} else { } else {
ck_assert(send_ret && msg_err == TOX_ERR_GROUP_SEND_MESSAGE_OK); ck_assert(msg_err == TOX_ERR_GROUP_SEND_MESSAGE_OK);
} }
break; break;
@@ -356,16 +360,16 @@ static void voice_state_message_test(AutoTox *autotox, Tox_Group_Voice_State voi
case TOX_GROUP_ROLE_MODERATOR: { case TOX_GROUP_ROLE_MODERATOR: {
if (voice_state != TOX_GROUP_VOICE_STATE_FOUNDER) { if (voice_state != TOX_GROUP_VOICE_STATE_FOUNDER) {
ck_assert(send_ret && msg_err == TOX_ERR_GROUP_SEND_MESSAGE_OK); ck_assert(msg_err == TOX_ERR_GROUP_SEND_MESSAGE_OK);
} else { } else {
ck_assert(!send_ret && msg_err == TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS); ck_assert(msg_err == TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS);
} }
break; break;
} }
case TOX_GROUP_ROLE_FOUNDER: { case TOX_GROUP_ROLE_FOUNDER: {
ck_assert(send_ret && msg_err == TOX_ERR_GROUP_SEND_MESSAGE_OK); ck_assert(msg_err == TOX_ERR_GROUP_SEND_MESSAGE_OK);
break; break;
} }
} }

View File

@@ -206,7 +206,7 @@ static void group_tcp_test(AutoTox *autotoxes)
Tox_Err_Group_Send_Message merr; Tox_Err_Group_Send_Message merr;
tox_group_send_message(autotoxes[0].tox, groupnumber, TOX_MESSAGE_TYPE_NORMAL, tox_group_send_message(autotoxes[0].tox, groupnumber, TOX_MESSAGE_TYPE_NORMAL,
(const uint8_t *)CODEWORD, CODEWORD_LEN, nullptr, &merr); (const uint8_t *)CODEWORD, CODEWORD_LEN, &merr);
ck_assert(merr == TOX_ERR_GROUP_SEND_MESSAGE_OK); ck_assert(merr == TOX_ERR_GROUP_SEND_MESSAGE_OK);
while (!state1->got_second_code) { while (!state1->got_second_code) {

View File

@@ -14,12 +14,14 @@
#include "auto_test_support.h" #include "auto_test_support.h"
#include "check_compat.h" #include "check_compat.h"
/* The Travis-CI container responds poorly to ::1 as a localhost address #ifndef USE_IPV6
* You're encouraged to -D FORCE_TESTS_IPV6 on a local test */ #define USE_IPV6 1
#endif
#ifdef TOX_LOCALHOST #ifdef TOX_LOCALHOST
#undef TOX_LOCALHOST #undef TOX_LOCALHOST
#endif #endif
#ifdef FORCE_TESTS_IPV6 #if USE_IPV6
#define TOX_LOCALHOST "::1" #define TOX_LOCALHOST "::1"
#else #else
#define TOX_LOCALHOST "127.0.0.1" #define TOX_LOCALHOST "127.0.0.1"
@@ -74,6 +76,7 @@ static void reload_tox(Tox **tox, struct Tox_Options *const in_opts, void *user_
} }
struct Tox_Options *const options = (in_opts == nullptr) ? tox_options_new(nullptr) : in_opts; struct Tox_Options *const options = (in_opts == nullptr) ? tox_options_new(nullptr) : in_opts;
tox_options_set_ipv6_enabled(options, USE_IPV6);
tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
@@ -138,6 +141,7 @@ static void test_few_clients(void)
time_t con_time = 0, cur_time = time(nullptr); time_t con_time = 0, cur_time = time(nullptr);
struct Tox_Options *opts1 = tox_options_new(nullptr); struct Tox_Options *opts1 = tox_options_new(nullptr);
tox_options_set_ipv6_enabled(opts1, USE_IPV6);
tox_options_set_tcp_port(opts1, TCP_RELAY_PORT); tox_options_set_tcp_port(opts1, TCP_RELAY_PORT);
Tox_Err_New t_n_error; Tox_Err_New t_n_error;
Tox *tox1 = tox_new_log(opts1, &t_n_error, &index[0]); Tox *tox1 = tox_new_log(opts1, &t_n_error, &index[0]);
@@ -145,12 +149,14 @@ static void test_few_clients(void)
tox_options_free(opts1); tox_options_free(opts1);
struct Tox_Options *opts2 = tox_options_new(nullptr); struct Tox_Options *opts2 = tox_options_new(nullptr);
tox_options_set_ipv6_enabled(opts2, USE_IPV6);
tox_options_set_udp_enabled(opts2, false); tox_options_set_udp_enabled(opts2, false);
tox_options_set_local_discovery_enabled(opts2, false); tox_options_set_local_discovery_enabled(opts2, false);
Tox *tox2 = tox_new_log(opts2, &t_n_error, &index[1]); Tox *tox2 = tox_new_log(opts2, &t_n_error, &index[1]);
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error); ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error);
struct Tox_Options *opts3 = tox_options_new(nullptr); struct Tox_Options *opts3 = tox_options_new(nullptr);
tox_options_set_ipv6_enabled(opts3, USE_IPV6);
tox_options_set_local_discovery_enabled(opts3, false); tox_options_set_local_discovery_enabled(opts3, false);
Tox *tox3 = tox_new_log(opts3, &t_n_error, &index[2]); Tox *tox3 = tox_new_log(opts3, &t_n_error, &index[2]);
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error); ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error);

View File

@@ -10,6 +10,7 @@
#include "../toxcore/tox.h" #include "../toxcore/tox.h"
#include "../toxcore/tox_dispatch.h" #include "../toxcore/tox_dispatch.h"
#include "../toxcore/tox_events.h" #include "../toxcore/tox_events.h"
#include "../toxcore/tox_private.h"
#include "../toxcore/tox_unpack.h" #include "../toxcore/tox_unpack.h"
#include "auto_test_support.h" #include "auto_test_support.h"
#include "check_compat.h" #include "check_compat.h"

View File

@@ -22,21 +22,23 @@ static bool await_message(Tox **toxes)
Tox_Events *events = tox_events_iterate(toxes[1], false, nullptr); Tox_Events *events = tox_events_iterate(toxes[1], false, nullptr);
if (events != nullptr) { if (events != nullptr) {
ck_assert(tox_events_get_friend_message_size(events) == 1); uint32_t events_size = tox_events_get_size(events);
const Tox_Event_Friend_Message *msg_event = tox_events_get_friend_message(events, 0); ck_assert(events_size == 1);
const Tox_Event_Friend_Message *msg_event = nullptr;
for (uint32_t j = 0; j < events_size; ++j) {
const Tox_Event *ev = tox_events_get(events, j);
if (tox_event_get_type(ev) == TOX_EVENT_FRIEND_MESSAGE) {
msg_event = tox_event_get_friend_message(ev);
}
}
ck_assert(msg_event != nullptr);
ck_assert(tox_event_friend_message_get_message_length(msg_event) == sizeof("hello")); ck_assert(tox_event_friend_message_get_message_length(msg_event) == sizeof("hello"));
const uint8_t *msg = tox_event_friend_message_get_message(msg_event); const uint8_t *msg = tox_event_friend_message_get_message(msg_event);
ck_assert_msg(memcmp(msg, "hello", sizeof("hello")) == 0, ck_assert_msg(memcmp(msg, "hello", sizeof("hello")) == 0,
"message was not expected 'hello' but '%s'", (const char *)msg); "message was not expected 'hello' but '%s'", (const char *)msg);
const uint32_t event_count = tox_events_get_size(events);
for (uint32_t j = 0; j < event_count; ++j) {
const Tox_Event *event = tox_events_get(events, j);
if (tox_event_get_type(event) == TOX_EVENT_FRIEND_MESSAGE) {
ck_assert(tox_event_get_friend_message(event) == msg_event);
}
}
tox_events_free(events); tox_events_free(events);
return true; return true;
} }

View File

@@ -13,9 +13,14 @@
#include "auto_test_support.h" #include "auto_test_support.h"
#include "check_compat.h" #include "check_compat.h"
/* The Travis-CI container responds poorly to ::1 as a localhost address #ifndef USE_IPV6
* You're encouraged to -D FORCE_TESTS_IPV6 on a local test */ #define USE_IPV6 1
#ifdef FORCE_TESTS_IPV6 #endif
#ifdef TOX_LOCALHOST
#undef TOX_LOCALHOST
#endif
#if USE_IPV6
#define TOX_LOCALHOST "::1" #define TOX_LOCALHOST "::1"
#else #else
#define TOX_LOCALHOST "127.0.0.1" #define TOX_LOCALHOST "127.0.0.1"

View File

@@ -1,19 +1,26 @@
############################################################################### ###############################################################################
# #
# :: For UNIX-like systems that have pkg-config. # :: For systems that have pkg-config.
# #
############################################################################### ###############################################################################
include(ModulePackage) find_package(PkgConfig REQUIRED)
find_package(Threads REQUIRED)
find_library(NSL_LIBRARIES nsl ) find_library(NSL_LIBRARIES nsl )
find_library(RT_LIBRARIES rt ) find_library(RT_LIBRARIES rt )
find_library(SOCKET_LIBRARIES socket) find_library(SOCKET_LIBRARIES socket)
find_package(pthreads QUIET)
if(NOT TARGET PThreads4W::PThreads4W)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
endif()
# For toxcore. # For toxcore.
pkg_search_module(LIBSODIUM libsodium IMPORTED_TARGET) pkg_search_module(LIBSODIUM libsodium IMPORTED_TARGET REQUIRED)
if(MSVC)
find_package(unofficial-sodium REQUIRED)
endif()
# For toxav. # For toxav.
pkg_search_module(OPUS opus IMPORTED_TARGET) pkg_search_module(OPUS opus IMPORTED_TARGET)
@@ -27,56 +34,3 @@ endif()
# For tox-bootstrapd. # For tox-bootstrapd.
pkg_search_module(LIBCONFIG libconfig IMPORTED_TARGET) pkg_search_module(LIBCONFIG libconfig IMPORTED_TARGET)
###############################################################################
#
# :: For MSVC Windows builds.
#
# These require specific installation paths of dependencies:
# - libsodium in third-party/libsodium/Win32/Release/v140/dynamic
# - pthreads in third-party/pthreads-win32/Pre-built.2
#
###############################################################################
if(MSVC)
# libsodium
# ---------
if(NOT LIBSODIUM_FOUND)
find_library(LIBSODIUM_LIBRARIES
NAMES sodium libsodium
PATHS
"third_party/libsodium/Win32/Release/v140/dynamic"
"third_party/libsodium/x64/Release/v140/dynamic"
)
if(LIBSODIUM_LIBRARIES)
include_directories("third_party/libsodium/include")
set(LIBSODIUM_FOUND TRUE)
message("libsodium: ${LIBSODIUM_LIBRARIES}")
else()
message(FATAL_ERROR "libsodium libraries not found")
endif()
endif()
# pthreads
# --------
if(CMAKE_USE_WIN32_THREADS_INIT)
find_library(CMAKE_THREAD_LIBS_INIT
NAMES pthreadVC2
PATHS
"third_party/pthreads-win32/Pre-built.2/lib/x86"
"third_party/pthreads-win32/Pre-built.2/lib/x64"
)
if(CMAKE_THREAD_LIBS_INIT)
include_directories("third_party/pthreads-win32/Pre-built.2/include")
add_definitions(-DHAVE_STRUCT_TIMESPEC)
message("libpthreads: ${CMAKE_THREAD_LIBS_INIT}")
else()
find_package(pthreads4w)
if(NOT pthreads4w_FOUND)
message(FATAL_ERROR "libpthreads libraries not found")
endif()
include_directories(${pthreads4w_INCLUDE_DIR})
link_libraries(${pthreads4w_LIBRARIES})
endif()
endif()
endif()

View File

@@ -19,21 +19,6 @@ if(FULLY_STATIC)
set(ENABLE_STATIC ON) set(ENABLE_STATIC ON)
endif() endif()
find_package(PkgConfig)
function(add_module lib)
set(${lib}_SOURCES ${ARGN} PARENT_SCOPE)
if(ENABLE_SHARED)
add_library(${lib}_shared SHARED ${ARGN})
set_target_properties(${lib}_shared PROPERTIES OUTPUT_NAME ${lib})
endif()
if(ENABLE_STATIC)
add_library(${lib}_static STATIC ${ARGN})
set_target_properties(${lib}_static PROPERTIES OUTPUT_NAME ${lib})
endif()
endfunction()
function(install_module lib) function(install_module lib)
if(TARGET ${lib}_shared) if(TARGET ${lib}_shared)
set_target_properties(${lib}_shared PROPERTIES set_target_properties(${lib}_shared PROPERTIES

View File

@@ -1,4 +0,0 @@
---
build:
docker:
web: other/bootstrap_daemon/websocket/Dockerfile

View File

@@ -21,13 +21,11 @@ cc_binary(
"//c-toxcore/toxcore:Messenger", "//c-toxcore/toxcore:Messenger",
"//c-toxcore/toxcore:TCP_server", "//c-toxcore/toxcore:TCP_server",
"//c-toxcore/toxcore:ccompat", "//c-toxcore/toxcore:ccompat",
"//c-toxcore/toxcore:friend_requests",
"//c-toxcore/toxcore:group_onion_announce", "//c-toxcore/toxcore:group_onion_announce",
"//c-toxcore/toxcore:logger", "//c-toxcore/toxcore:logger",
"//c-toxcore/toxcore:mono_time", "//c-toxcore/toxcore:mono_time",
"//c-toxcore/toxcore:network", "//c-toxcore/toxcore:network",
"//c-toxcore/toxcore:onion_announce", "//c-toxcore/toxcore:onion_announce",
"//c-toxcore/toxcore:tox", "//c-toxcore/toxcore:tox",
"//c-toxcore/toxcore:util",
], ],
) )

View File

@@ -16,12 +16,17 @@
#include "../toxcore/DHT.h" #include "../toxcore/DHT.h"
#include "../toxcore/LAN_discovery.h" #include "../toxcore/LAN_discovery.h"
#include "../toxcore/ccompat.h" #include "../toxcore/ccompat.h"
#include "../toxcore/friend_requests.h" #include "../toxcore/crypto_core.h"
#include "../toxcore/forwarding.h"
#include "../toxcore/group_announce.h"
#include "../toxcore/group_onion_announce.h" #include "../toxcore/group_onion_announce.h"
#include "../toxcore/logger.h" #include "../toxcore/logger.h"
#include "../toxcore/mem.h"
#include "../toxcore/mono_time.h" #include "../toxcore/mono_time.h"
#include "../toxcore/network.h"
#include "../toxcore/onion.h"
#include "../toxcore/onion_announce.h"
#include "../toxcore/tox.h" #include "../toxcore/tox.h"
#include "../toxcore/util.h"
#define TCP_RELAY_ENABLED #define TCP_RELAY_ENABLED
@@ -46,7 +51,7 @@ static const char *motd_str = ""; //Change this to anything within 256 bytes(but
#define PORT 33445 #define PORT 33445
static void manage_keys(DHT *dht) static bool manage_keys(DHT *dht)
{ {
enum { KEYS_SIZE = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE }; enum { KEYS_SIZE = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE };
uint8_t keys[KEYS_SIZE]; uint8_t keys[KEYS_SIZE];
@@ -60,7 +65,8 @@ static void manage_keys(DHT *dht)
if (read_size != KEYS_SIZE) { if (read_size != KEYS_SIZE) {
printf("Error while reading the key file\nExiting.\n"); printf("Error while reading the key file\nExiting.\n");
exit(1); fclose(keys_file);
return false;
} }
dht_set_self_public_key(dht, keys); dht_set_self_public_key(dht, keys);
@@ -73,18 +79,20 @@ static void manage_keys(DHT *dht)
if (keys_file == nullptr) { if (keys_file == nullptr) {
printf("Error opening key file in write mode.\nKeys will not be saved.\n"); printf("Error opening key file in write mode.\nKeys will not be saved.\n");
return; return false;
} }
if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file) != KEYS_SIZE) { if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file) != KEYS_SIZE) {
printf("Error while writing the key file.\nExiting.\n"); printf("Error while writing the key file.\nExiting.\n");
exit(1); fclose(keys_file);
return false;
} }
printf("Keys saved successfully.\n"); printf("Keys saved successfully.\n");
} }
fclose(keys_file); fclose(keys_file);
return true;
} }
static const char *strlevel(Logger_Level level) static const char *strlevel(Logger_Level level)
@@ -121,7 +129,7 @@ int main(int argc, char *argv[])
if (argc == 2 && !tox_strncasecmp(argv[1], "-h", 3)) { if (argc == 2 && !tox_strncasecmp(argv[1], "-h", 3)) {
printf("Usage (connected) : %s [--ipv4|--ipv6] IP PORT KEY\n", argv[0]); printf("Usage (connected) : %s [--ipv4|--ipv6] IP PORT KEY\n", argv[0]);
printf("Usage (unconnected): %s [--ipv4|--ipv6]\n", argv[0]); printf("Usage (unconnected): %s [--ipv4|--ipv6]\n", argv[0]);
exit(0); return 0;
} }
/* let user override default by cmdline */ /* let user override default by cmdline */
@@ -129,7 +137,7 @@ int main(int argc, char *argv[])
int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
if (argvoffset < 0) { if (argvoffset < 0) {
exit(1); return 1;
} }
/* Initialize networking - /* Initialize networking -
@@ -162,14 +170,16 @@ int main(int argc, char *argv[])
if (!(onion && forwarding && onion_a)) { if (!(onion && forwarding && onion_a)) {
printf("Something failed to initialize.\n"); printf("Something failed to initialize.\n");
exit(1); return 1;
} }
gca_onion_init(gc_announces_list, onion_a); gca_onion_init(gc_announces_list, onion_a);
perror("Initialization"); perror("Initialization");
manage_keys(dht); if (!manage_keys(dht)) {
return 1;
}
printf("Public key: "); printf("Public key: ");
#ifdef TCP_RELAY_ENABLED #ifdef TCP_RELAY_ENABLED
@@ -179,7 +189,7 @@ int main(int argc, char *argv[])
if (tcp_s == nullptr) { if (tcp_s == nullptr) {
printf("TCP server failed to initialize.\n"); printf("TCP server failed to initialize.\n");
exit(1); return 1;
} }
#endif #endif
@@ -189,7 +199,7 @@ int main(int argc, char *argv[])
if (file == nullptr) { if (file == nullptr) {
printf("Could not open file \"%s\" for writing. Exiting...\n", public_id_filename); printf("Could not open file \"%s\" for writing. Exiting...\n", public_id_filename);
exit(1); return 1;
} }
for (uint32_t i = 0; i < 32; ++i) { for (uint32_t i = 0; i < 32; ++i) {
@@ -210,7 +220,7 @@ int main(int argc, char *argv[])
if (port_conv <= 0 || port_conv > UINT16_MAX) { if (port_conv <= 0 || port_conv > UINT16_MAX) {
printf("Failed to convert \"%s\" into a valid port. Exiting...\n", argv[argvoffset + 2]); printf("Failed to convert \"%s\" into a valid port. Exiting...\n", argv[argvoffset + 2]);
exit(1); return 1;
} }
const uint16_t port = net_htons((uint16_t)port_conv); const uint16_t port = net_htons((uint16_t)port_conv);
@@ -222,7 +232,7 @@ int main(int argc, char *argv[])
if (!res) { if (!res) {
printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]); printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]);
exit(1); return 1;
} }
} }

View File

@@ -31,8 +31,8 @@ out = (subprocess.run(
errors = 0 errors = 0
for line in out.split("\n"): for line in out.split("\n"):
# other/fun can do what it wants. # other/fun and mallocfail can do what they want.
if "/fun/" in line: if "/fun/" in line or "/mallocfail/" in line:
continue continue
filename, include = line.split(":", 1) filename, include = line.split(":", 1)
# We only check headers. # We only check headers.

View File

@@ -15,7 +15,7 @@ CPPFLAGS+=("-Itoxav")
CPPFLAGS+=("-Itoxencryptsave") CPPFLAGS+=("-Itoxencryptsave")
CPPFLAGS+=("-Ithird_party/cmp") CPPFLAGS+=("-Ithird_party/cmp")
LDFLAGS=("-lopus" "-lsodium" "-lvpx" "-lpthread" "-lconfig" "-lgtest") LDFLAGS=("-lopus" "-lsodium" "-lvpx" "-lpthread" "-lconfig" "-lgmock" "-lgtest")
LDFLAGS+=("-fuse-ld=gold") LDFLAGS+=("-fuse-ld=gold")
LDFLAGS+=("-Wl,--detect-odr-violations") LDFLAGS+=("-Wl,--detect-odr-violations")
LDFLAGS+=("-Wl,--warn-common") LDFLAGS+=("-Wl,--warn-common")

View File

@@ -10,7 +10,7 @@ run() {
"${CPPFLAGS[@]}" \ "${CPPFLAGS[@]}" \
"${LDFLAGS[@]}" \ "${LDFLAGS[@]}" \
"$@" \ "$@" \
-std=c++11 \ -std=c++17 \
-Werror \ -Werror \
-Weverything \ -Weverything \
-Wno-alloca \ -Wno-alloca \

View File

@@ -9,7 +9,7 @@ run() {
clang++ --analyze amalgamation.cc \ clang++ --analyze amalgamation.cc \
"${CPPFLAGS[@]}" \ "${CPPFLAGS[@]}" \
"$@" \ "$@" \
-std=c++11 -std=c++20
} }
. other/analysis/variants.sh . other/analysis/variants.sh

View File

@@ -1,6 +1,64 @@
#!/bin/bash #!/usr/bin/env bash
CHECKS="*" CHECKS="*"
ERRORS="*"
# Need to investigate or disable and document these.
# =========================================================
# TODO(iphydf): Fix these.
ERRORS="$ERRORS,-cert-err34-c"
ERRORS="$ERRORS,-readability-suspicious-call-argument"
# TODO(iphydf): Fix once cimple 0.0.19 is released.
CHECKS="$CHECKS,-google-readability-casting"
# TODO(iphydf): Fix these.
CHECKS="$CHECKS,-bugprone-switch-missing-default-case"
# TODO(iphydf): We might want some of these. For the ones we don't want, add a
# comment explaining why not.
CHECKS="$CHECKS,-clang-analyzer-optin.performance.Padding"
CHECKS="$CHECKS,-hicpp-signed-bitwise"
# TODO(iphydf): Maybe fix these?
CHECKS="$CHECKS,-bugprone-implicit-widening-of-multiplication-result"
CHECKS="$CHECKS,-bugprone-integer-division"
CHECKS="$CHECKS,-misc-no-recursion"
# TODO(iphydf): Only happens in bootstrap_daemon. Fix it.
CHECKS="$CHECKS,-cppcoreguidelines-avoid-non-const-global-variables"
# TODO(iphydf): Probably fix these.
CHECKS="$CHECKS,-cert-err33-c"
CHECKS="$CHECKS,-cppcoreguidelines-avoid-magic-numbers"
CHECKS="$CHECKS,-readability-magic-numbers"
# TODO(iphydf): We're using a lot of macros for constants. Should we convert
# all of them to enum?
CHECKS="$CHECKS,-modernize-macro-to-enum"
# Documented disabled checks. We don't want these for sure.
# =========================================================
# https://stackoverflow.com/questions/58672959/why-does-clang-tidy-say-vsnprintf-has-an-uninitialized-va-list-argument
CHECKS="$CHECKS,-clang-analyzer-valist.Uninitialized"
# We pass a lot of ints around, so many function parameters are some kind of
# int type that can be converted from another int type. We won't be getting
# away from that anytime soon.
CHECKS="$CHECKS,-bugprone-easily-swappable-parameters"
# Callback handlers often don't use all their parameters. There's
# IgnoreVirtual, but that doesn't work for C-style callbacks.
CHECKS="$CHECKS,-misc-unused-parameters"
# We sometimes use #if 0.
CHECKS="$CHECKS,-readability-avoid-unconditional-preprocessor-if"
# We have better macro hygiene checks with tokstyle. We can never pass macro
# arguments that require parentheses inside the macro.
CHECKS="$CHECKS,-bugprone-macro-parentheses"
# We don't use memcpy_s. # We don't use memcpy_s.
CHECKS="$CHECKS,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling" CHECKS="$CHECKS,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling"
@@ -81,62 +139,48 @@ CHECKS="$CHECKS,-cert-dcl03-c"
CHECKS="$CHECKS,-hicpp-static-assert" CHECKS="$CHECKS,-hicpp-static-assert"
CHECKS="$CHECKS,-misc-static-assert" CHECKS="$CHECKS,-misc-static-assert"
# TODO(iphydf): We might want some of these. For the ones we don't want, add a
# comment explaining why not.
CHECKS="$CHECKS,-clang-analyzer-optin.performance.Padding"
CHECKS="$CHECKS,-hicpp-signed-bitwise"
CHECKS="$CHECKS,-misc-unused-parameters"
CHECKS="$CHECKS,-readability-function-cognitive-complexity"
# TODO(iphydf): Maybe fix these?
CHECKS="$CHECKS,-bugprone-easily-swappable-parameters"
CHECKS="$CHECKS,-bugprone-implicit-widening-of-multiplication-result"
CHECKS="$CHECKS,-bugprone-integer-division"
CHECKS="$CHECKS,-clang-analyzer-core.NullDereference"
CHECKS="$CHECKS,-clang-analyzer-valist.Uninitialized"
CHECKS="$CHECKS,-concurrency-mt-unsafe"
CHECKS="$CHECKS,-cppcoreguidelines-avoid-non-const-global-variables"
CHECKS="$CHECKS,-misc-no-recursion"
# TODO(iphydf): Probably fix these.
CHECKS="$CHECKS,-cert-err33-c"
CHECKS="$CHECKS,-cppcoreguidelines-avoid-magic-numbers"
CHECKS="$CHECKS,-google-readability-casting"
CHECKS="$CHECKS,-modernize-macro-to-enum"
CHECKS="$CHECKS,-readability-magic-numbers"
# TODO(iphydf): These two trip on list.c. Investigate why.
CHECKS="$CHECKS,-clang-analyzer-core.NonNullParamChecker"
CHECKS="$CHECKS,-clang-analyzer-unix.Malloc"
ERRORS="*"
# TODO(iphydf): Fix these.
ERRORS="$ERRORS,-bugprone-macro-parentheses"
ERRORS="$ERRORS,-cert-err34-c"
ERRORS="$ERRORS,-cert-str34-c"
ERRORS="$ERRORS,-readability-suspicious-call-argument"
set -eux set -eux
# TODO(iphydf): Add toxav.
DIRS=(
other/bootstrap_daemon/src
other
toxcore
toxcore/events
toxencryptsave
)
copy_files() {
find "${DIRS[@]}" \
-maxdepth 1 -type d -exec mkdir -p "$1/{}" \;
find "${DIRS[@]}" \
-maxdepth 1 -name "*.c" -exec cp "{}" "$1/{}" \;
}
run() { run() {
echo "Running clang-tidy in variant '$*'" echo "Running clang-tidy in variant '$*'"
EXTRA_ARGS=("$@") EXTRA_ARGS=("$@")
for i in "${!EXTRA_ARGS[@]}"; do for i in "${!EXTRA_ARGS[@]}"; do
EXTRA_ARGS[$i]="--extra-arg=${EXTRA_ARGS[$i]}" EXTRA_ARGS[$i]="--extra-arg=${EXTRA_ARGS[$i]}"
done done
clang-tidy-14 \ ls .clang-tidy
-p=_build \ copy_files a
--extra-arg=-DMIN_LOGGER_LEVEL=LOGGER_LEVEL_TRACE \ if ! find "${DIRS[@]}" \
"${EXTRA_ARGS[@]}" \ -maxdepth 1 -name "*.c" -print0 \
--checks="$CHECKS" \ | xargs -0 -n15 -P"$(nproc)" clang-tidy \
--warnings-as-errors="$ERRORS" \ -p="$PWD/_build" \
--use-color \ --extra-arg=-DMIN_LOGGER_LEVEL=LOGGER_LEVEL_TRACE \
other/bootstrap_daemon/src/*.c \ "${EXTRA_ARGS[@]}" \
other/*.c \ --fix \
toxav/*.c \ --checks="$CHECKS" \
toxcore/*.c \ --warnings-as-errors="$ERRORS" \
toxencryptsave/*.c --use-color; then
copy_files b
colordiff -ru a b
rm -rf a b
false
fi
rm -rf a
} }
cmake . -B_build -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON cmake . -B_build -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

View File

@@ -34,6 +34,8 @@ CPPCHECK_CXX+=("--suppress=AssignmentAddressToInteger")
CPPCHECK_CXX+=("--suppress=cstyleCast") CPPCHECK_CXX+=("--suppress=cstyleCast")
# Used in Messenger.c for a static_assert(...) # Used in Messenger.c for a static_assert(...)
CPPCHECK_CXX+=("--suppress=sizeofFunctionCall") CPPCHECK_CXX+=("--suppress=sizeofFunctionCall")
# This is outdated. Range-for is a good choice.
CPPCHECK_CXX+=("--suppress=useStlAlgorithm")
run() { run() {
echo "Running cppcheck in variant '$*'" echo "Running cppcheck in variant '$*'"

View File

@@ -11,7 +11,7 @@ run() {
"${CPPFLAGS[@]}" \ "${CPPFLAGS[@]}" \
"${LDFLAGS[@]}" \ "${LDFLAGS[@]}" \
"$@" \ "$@" \
-std=c++11 \ -std=c++17 \
-fdiagnostics-color=always \ -fdiagnostics-color=always \
-Wall \ -Wall \
-Wextra \ -Wextra \

View File

@@ -1,25 +0,0 @@
#!/bin/sh
# --bufferoverrun \
# --pulse \
read -r -d '' SCRIPT <<'EOF'
infer \
--report-console-limit 100 \
--jobs 8 \
--biabduction \
--loop-hoisting \
--quandary \
--racerd \
--starvation \
--uninit \
-- clang++ -fsyntax-only \
$(pkg-config --cflags libconfig libsodium opus vpx) \
/work/other/bootstrap_daemon/src/*.c \
/work/other/bootstrap_node_packets.c \
/work/toxav/*.c \
/work/toxcore/*.c \
/work/toxencryptsave/*.c
EOF
docker run --rm -it -v "$PWD:/work" toxchat/infer bash -c "$SCRIPT"

View File

@@ -16,7 +16,6 @@
--align-reference=name --align-reference=name
# Formatting Options # Formatting Options
--add-brackets
--convert-tabs --convert-tabs
--max-code-length=120 --max-code-length=120

View File

@@ -18,7 +18,6 @@ cc_binary(
"//c-toxcore/toxcore:mono_time", "//c-toxcore/toxcore:mono_time",
"//c-toxcore/toxcore:onion_announce", "//c-toxcore/toxcore:onion_announce",
"//c-toxcore/toxcore:tox", "//c-toxcore/toxcore:tox",
"//c-toxcore/toxcore:util",
"@libconfig", "@libconfig",
], ],
) )

View File

@@ -259,7 +259,7 @@ docker run -d --name tox-bootstrapd --restart always \
toxchat/bootstrap-node toxchat/bootstrap-node
``` ```
We create a new user and protect its home directory in order to mount it in the Docker image, so that the kyepair the daemon uses would be stored on the host system, which makes it less likely that you would loose the keypair while playing with or updating the Docker container. We create a new user and protect its home directory in order to mount it in the Docker image, so that the keypair the daemon uses would be stored on the host system, which makes it less likely that you would loose the keypair while playing with or updating the Docker container.
You can check logs for your public key or any errors: You can check logs for your public key or any errors:
```sh ```sh

View File

@@ -12,8 +12,7 @@ RUN ["apk", "--no-cache", "add",\
"libsodium-static",\ "libsodium-static",\
"musl-dev",\ "musl-dev",\
"ninja",\ "ninja",\
"python3"\ "python3"]
]
WORKDIR /src/c-toxcore WORKDIR /src/c-toxcore
@@ -49,8 +48,10 @@ RUN CC=clang cmake -B_build -H. \
# Verify checksum from dev-built binary, so we can be sure Docker Hub doesn't # Verify checksum from dev-built binary, so we can be sure Docker Hub doesn't
# mess with your binaries. # mess with your binaries.
COPY other/bootstrap_daemon/docker/tox-bootstrapd.sha256 other/bootstrap_daemon/docker/ COPY other/bootstrap_daemon/docker/tox-bootstrapd.sha256 other/bootstrap_daemon/docker/
RUN sha256sum /usr/local/bin/tox-bootstrapd && \ RUN SHA256="$(sha256sum /usr/local/bin/tox-bootstrapd)" && \
sha256sum -c other/bootstrap_daemon/docker/tox-bootstrapd.sha256 (sha256sum -c other/bootstrap_daemon/docker/tox-bootstrapd.sha256 || \
(echo "::error file=other/bootstrap_daemon/docker/tox-bootstrapd.sha256,line=1::$SHA256" && \
false))
# Remove all the example bootstrap nodes from the config file. # Remove all the example bootstrap nodes from the config file.
COPY other/bootstrap_daemon/tox-bootstrapd.conf other/bootstrap_daemon/ COPY other/bootstrap_daemon/tox-bootstrapd.conf other/bootstrap_daemon/

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env python3
import json
import os
import pprint
import subprocess
import sys
import urllib.request
from typing import Any
SHA256_FILE = "other/bootstrap_daemon/docker/tox-bootstrapd.sha256"
with open(f"{os.environ['HOME']}/.github-token") as fh:
token = fh.read().strip()
head_sha = (subprocess.run(["git", "rev-parse", "HEAD"],
capture_output=True,
check=True).stdout.decode("utf-8").strip())
def request(url: str) -> Any:
return json.loads(
urllib.request.urlopen(
urllib.request.Request(
url,
headers={
"Accept": "application/vnd.github+json",
"Authorization": "Bearer " + token,
"X-GitHub-Api-Version": "2022-11-28",
},
)).read())
pp = pprint.PrettyPrinter(indent=2, compact=True)
annots = [
a for r in request(
f"https://api.github.com/repos/TokTok/c-toxcore/commits/{head_sha}/check-runs?per_page=100"
)["check_runs"] if r["name"] == "docker-bootstrap-node"
for a in request(r["output"]["annotations_url"])
if a["path"] == SHA256_FILE
]
if not annots:
print("could not find sha256sum output")
sys.exit(1)
with open(SHA256_FILE, "w") as fh:
fh.write(annots[0]["message"] + "\n")
print(f"updated {SHA256_FILE}")

View File

@@ -1 +1 @@
b0bd5099f2f77fbd540a5a929a23cece39ff95e3a66702a5381342d01775cbd3 /usr/local/bin/tox-bootstrapd 0b904988d79b9576bb88c6c7316d107b5a61bd6119a0992ebd7c1fa43db70abf /usr/local/bin/tox-bootstrapd

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2018 The TokTok team. * Copyright © 2016-2024 The TokTok team.
* Copyright © 2015-2016 Tox project. * Copyright © 2015-2016 Tox project.
*/ */
@@ -10,12 +10,12 @@
#include "command_line_arguments.h" #include "command_line_arguments.h"
#include "global.h" #include "global.h"
#include "log.h"
#include "../../../toxcore/ccompat.h" #include "../../../toxcore/ccompat.h"
#include <getopt.h> #include <getopt.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
@@ -24,9 +24,9 @@
*/ */
static void print_help(void) static void print_help(void)
{ {
// 2 space ident // 2 space indent
// make sure all lines fit into 80 columns // Make sure all lines fit into 80 columns
// make sure options are listed in alphabetical order // Make sure options are listed in alphabetical order
log_write(LOG_LEVEL_INFO, log_write(LOG_LEVEL_INFO,
"Usage: tox-bootstrapd [OPTION]... --config=FILE_PATH\n" "Usage: tox-bootstrapd [OPTION]... --config=FILE_PATH\n"
"\n" "\n"
@@ -39,7 +39,7 @@ static void print_help(void)
" (detach from the terminal) and won't use the PID file.\n" " (detach from the terminal) and won't use the PID file.\n"
" --help Print this help message.\n" " --help Print this help message.\n"
" --log-backend=BACKEND Specify which logging backend to use.\n" " --log-backend=BACKEND Specify which logging backend to use.\n"
" Valid BACKEND values (case sensetive):\n" " Valid BACKEND values (case sensitive):\n"
" syslog Writes log messages to syslog.\n" " syslog Writes log messages to syslog.\n"
" Default option when no --log-backend is\n" " Default option when no --log-backend is\n"
" specified.\n" " specified.\n"
@@ -47,13 +47,14 @@ static void print_help(void)
" --version Print version information.\n"); " --version Print version information.\n");
} }
void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend, Cli_Status handle_command_line_arguments(
bool *run_in_foreground) int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend,
bool *run_in_foreground)
{ {
if (argc < 2) { if (argc < 2) {
log_write(LOG_LEVEL_ERROR, "Error: No arguments provided.\n\n"); log_write(LOG_LEVEL_ERROR, "Error: No arguments provided.\n\n");
print_help(); print_help();
exit(1); return CLI_STATUS_ERROR;
} }
opterr = 0; opterr = 0;
@@ -89,7 +90,7 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path,
case 'h': case 'h':
print_help(); print_help();
exit(0); return CLI_STATUS_DONE;
case 'l': case 'l':
if (strcmp(optarg, "syslog") == 0) { if (strcmp(optarg, "syslog") == 0) {
@@ -101,24 +102,24 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path,
} else { } else {
log_write(LOG_LEVEL_ERROR, "Error: Invalid BACKEND value for --log-backend option passed: %s\n\n", optarg); log_write(LOG_LEVEL_ERROR, "Error: Invalid BACKEND value for --log-backend option passed: %s\n\n", optarg);
print_help(); print_help();
exit(1); return CLI_STATUS_ERROR;
} }
break; break;
case 'v': case 'v':
log_write(LOG_LEVEL_INFO, "Version: %lu\n", DAEMON_VERSION_NUMBER); log_write(LOG_LEVEL_INFO, "Version: %lu\n", DAEMON_VERSION_NUMBER);
exit(0); return CLI_STATUS_DONE;
case '?': case '?':
log_write(LOG_LEVEL_ERROR, "Error: Unrecognized option %s\n\n", argv[optind - 1]); log_write(LOG_LEVEL_ERROR, "Error: Unrecognized option %s\n\n", argv[optind - 1]);
print_help(); print_help();
exit(1); return CLI_STATUS_ERROR;
case ':': case ':':
log_write(LOG_LEVEL_ERROR, "Error: No argument provided for option %s\n\n", argv[optind - 1]); log_write(LOG_LEVEL_ERROR, "Error: No argument provided for option %s\n\n", argv[optind - 1]);
print_help(); print_help();
exit(1); return CLI_STATUS_ERROR;
} }
} }
@@ -129,6 +130,8 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path,
if (!cfg_file_path_set) { if (!cfg_file_path_set) {
log_write(LOG_LEVEL_ERROR, "Error: The required --config option wasn't specified\n\n"); log_write(LOG_LEVEL_ERROR, "Error: The required --config option wasn't specified\n\n");
print_help(); print_help();
exit(1); return CLI_STATUS_ERROR;
} }
return CLI_STATUS_OK;
} }

View File

@@ -12,6 +12,15 @@
#include "log.h" #include "log.h"
typedef enum Cli_Status {
/** Continue the program. Command line processing completed. */
CLI_STATUS_OK,
/** Stop the program with success status. */
CLI_STATUS_DONE,
/** Stop the program with error status. */
CLI_STATUS_ERROR,
} Cli_Status;
/** /**
* Handles command line arguments, setting cfg_file_path and log_backend. * Handles command line arguments, setting cfg_file_path and log_backend.
* Terminates the application if incorrect arguments are specified. * Terminates the application if incorrect arguments are specified.
@@ -22,7 +31,8 @@
* @param log_backend Sets to the provided by the user log backend option. * @param log_backend Sets to the provided by the user log backend option.
* @param run_in_foreground Sets to the provided by the user foreground option. * @param run_in_foreground Sets to the provided by the user foreground option.
*/ */
void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend, Cli_Status handle_command_line_arguments(
bool *run_in_foreground); int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend,
bool *run_in_foreground);
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_COMMAND_LINE_ARGUMENTS_H #endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_COMMAND_LINE_ARGUMENTS_H

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2023 The TokTok team. * Copyright © 2016-2024 The TokTok team.
* Copyright © 2014-2016 Tox project. * Copyright © 2014-2016 Tox project.
*/ */
@@ -10,6 +10,7 @@
#include "config.h" #include "config.h"
#include "config_defaults.h" #include "config_defaults.h"
#include "global.h"
#include "log.h" #include "log.h"
#include <stdio.h> #include <stdio.h>
@@ -18,6 +19,10 @@
#include <libconfig.h> #include <libconfig.h>
#include "../../../toxcore/DHT.h"
#include "../../../toxcore/ccompat.h"
#include "../../../toxcore/crypto_core.h"
#include "../../../toxcore/network.h"
#include "../../bootstrap_node_packets.h" #include "../../bootstrap_node_packets.h"
/** /**
@@ -51,7 +56,7 @@ static void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_por
log_write(LOG_LEVEL_INFO, "Port #%zu: %u\n", i, default_ports[i]); log_write(LOG_LEVEL_INFO, "Port #%zu: %u\n", i, default_ports[i]);
} }
// similar procedure to the one of reading config file below // Similar procedure to the one of reading config file below
*tcp_relay_ports = (uint16_t *)malloc(default_ports_count * sizeof(uint16_t)); *tcp_relay_ports = (uint16_t *)malloc(default_ports_count * sizeof(uint16_t));
for (size_t i = 0; i < default_ports_count; ++i) { for (size_t i = 0; i < default_ports_count; ++i) {
@@ -68,7 +73,7 @@ static void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_por
++*tcp_relay_port_count; ++*tcp_relay_port_count;
} }
// the loop above skips invalid ports, so we adjust the allocated memory size // The loop above skips invalid ports, so we adjust the allocated memory size
if ((*tcp_relay_port_count) > 0) { if ((*tcp_relay_port_count) > 0) {
*tcp_relay_ports = (uint16_t *)realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); *tcp_relay_ports = (uint16_t *)realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t));
} else { } else {
@@ -98,7 +103,7 @@ static void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_por
config_setting_t *elem = config_setting_get_elem(ports_array, i); config_setting_t *elem = config_setting_get_elem(ports_array, i);
if (elem == nullptr) { if (elem == nullptr) {
// it's NULL if `ports_array` is not an array (we have that check earlier) or if `i` is out of range, which should not be // It's NULL if `ports_array` is not an array (we have that check earlier) or if `i` is out of range, which should not be
log_write(LOG_LEVEL_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i); log_write(LOG_LEVEL_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i);
break; break;
} }
@@ -120,7 +125,7 @@ static void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_por
++*tcp_relay_port_count; ++*tcp_relay_port_count;
} }
// the loop above skips invalid ports, so we adjust the allocated memory size // The loop above skips invalid ports, so we adjust the allocated memory size
if ((*tcp_relay_port_count) > 0) { if ((*tcp_relay_port_count) > 0) {
*tcp_relay_ports = (uint16_t *)realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); *tcp_relay_ports = (uint16_t *)realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t));
} else { } else {
@@ -260,7 +265,7 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false");
// show info about tcp ports only if tcp relay is enabled // Show info about tcp ports only if tcp relay is enabled
if (*enable_tcp_relay) { if (*enable_tcp_relay) {
if (*tcp_relay_port_count == 0) { if (*tcp_relay_port_count == 0) {
log_write(LOG_LEVEL_ERROR, "No TCP ports could be read.\n"); log_write(LOG_LEVEL_ERROR, "No TCP ports could be read.\n");
@@ -407,7 +412,7 @@ int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6)
log_write(LOG_LEVEL_INFO, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key); log_write(LOG_LEVEL_INFO, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key);
next: next:
// config_setting_lookup_string() allocates string inside and doesn't allow us to free it direcly // config_setting_lookup_string() allocates string inside and doesn't allow us to free it directly
// though it's freed when the element is removed, so we free it right away in order to keep memory // though it's freed when the element is removed, so we free it right away in order to keep memory
// consumption minimal // consumption minimal
config_setting_remove_elem(node_list, 0); config_setting_remove_elem(node_list, 0);

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2018 The TokTok team. * Copyright © 2016-2024 The TokTok team.
* Copyright © 2014-2016 Tox project. * Copyright © 2014-2016 Tox project.
*/ */
@@ -30,7 +30,7 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k
* Bootstraps off nodes listed in the config file. * Bootstraps off nodes listed in the config file.
* *
* @return 1 on success, some or no bootstrap nodes were added * @return 1 on success, some or no bootstrap nodes were added
* 0 on failure, a error accured while parsing config file. * 0 on failure, an error occurred while parsing the config file.
*/ */
int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6); int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6);

View File

@@ -3,6 +3,8 @@
* Copyright © 2015-2016 Tox project. * Copyright © 2015-2016 Tox project.
*/ */
#include <stdarg.h>
/* /*
* Tox DHT bootstrap daemon. * Tox DHT bootstrap daemon.
* Logging utility with support of multiple logging backends. * Logging utility with support of multiple logging backends.

View File

@@ -9,8 +9,11 @@
*/ */
#include "log_backend_stdout.h" #include "log_backend_stdout.h"
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include "log.h"
static FILE *log_backend_stdout_level(LOG_LEVEL level) static FILE *log_backend_stdout_level(LOG_LEVEL level)
{ {
switch (level) { switch (level) {

View File

@@ -10,10 +10,12 @@
#include "log_backend_syslog.h" #include "log_backend_syslog.h"
#include "global.h" #include "global.h"
#include "log.h"
#include "../../../toxcore/ccompat.h" #include "../../../toxcore/ccompat.h"
#include <assert.h> #include <assert.h>
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <syslog.h> #include <syslog.h>

View File

@@ -23,17 +23,24 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
// toxcore // toxcore
#include "../../../toxcore/tox.h" #include "../../../toxcore/DHT.h"
#include "../../../toxcore/LAN_discovery.h" #include "../../../toxcore/LAN_discovery.h"
#include "../../../toxcore/TCP_server.h" #include "../../../toxcore/TCP_server.h"
#include "../../../toxcore/announce.h" #include "../../../toxcore/announce.h"
#include "../../../toxcore/ccompat.h"
#include "../../../toxcore/crypto_core.h"
#include "../../../toxcore/forwarding.h"
#include "../../../toxcore/group_announce.h"
#include "../../../toxcore/group_onion_announce.h" #include "../../../toxcore/group_onion_announce.h"
#include "../../../toxcore/logger.h" #include "../../../toxcore/logger.h"
#include "../../../toxcore/mem.h"
#include "../../../toxcore/mono_time.h" #include "../../../toxcore/mono_time.h"
#include "../../../toxcore/network.h"
#include "../../../toxcore/onion.h"
#include "../../../toxcore/onion_announce.h" #include "../../../toxcore/onion_announce.h"
#include "../../../toxcore/util.h"
// misc // misc
#include "../../bootstrap_node_packets.h" #include "../../bootstrap_node_packets.h"
@@ -116,7 +123,7 @@ static void print_public_key(const uint8_t *public_key)
// Demonizes the process, appending PID to the PID file and closing file descriptors based on log backend // Demonizes the process, appending PID to the PID file and closing file descriptors based on log backend
// Terminates the application if the daemonization fails. // Terminates the application if the daemonization fails.
static void daemonize(LOG_BACKEND log_backend, char *pid_file_path) static Cli_Status daemonize(LOG_BACKEND log_backend, char *pid_file_path)
{ {
// Check if the PID file exists // Check if the PID file exists
FILE *pid_file = fopen(pid_file_path, "r"); FILE *pid_file = fopen(pid_file_path, "r");
@@ -131,7 +138,7 @@ static void daemonize(LOG_BACKEND log_backend, char *pid_file_path)
if (pid_file == nullptr) { if (pid_file == nullptr) {
log_write(LOG_LEVEL_ERROR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path); log_write(LOG_LEVEL_ERROR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path);
exit(1); return CLI_STATUS_ERROR;
} }
// Fork off from the parent process // Fork off from the parent process
@@ -141,27 +148,27 @@ static void daemonize(LOG_BACKEND log_backend, char *pid_file_path)
fprintf(pid_file, "%d", pid); fprintf(pid_file, "%d", pid);
fclose(pid_file); fclose(pid_file);
log_write(LOG_LEVEL_INFO, "Forked successfully: PID: %d.\n", pid); log_write(LOG_LEVEL_INFO, "Forked successfully: PID: %d.\n", pid);
exit(0); return CLI_STATUS_DONE;
} else { } else {
fclose(pid_file); fclose(pid_file);
} }
if (pid < 0) { if (pid < 0) {
log_write(LOG_LEVEL_ERROR, "Forking failed. Exiting.\n"); log_write(LOG_LEVEL_ERROR, "Forking failed. Exiting.\n");
exit(1); return CLI_STATUS_ERROR;
} }
// Create a new SID for the child process // Create a new SID for the child process
if (setsid() < 0) { if (setsid() < 0) {
log_write(LOG_LEVEL_ERROR, "SID creation failure. Exiting.\n"); log_write(LOG_LEVEL_ERROR, "SID creation failure. Exiting.\n");
exit(1); return CLI_STATUS_ERROR;
} }
// Change the current working directory // Change the current working directory
if ((chdir("/")) < 0) { if ((chdir("/")) < 0) {
log_write(LOG_LEVEL_ERROR, "Couldn't change working directory to '/'. Exiting.\n"); log_write(LOG_LEVEL_ERROR, "Couldn't change working directory to '/'. Exiting.\n");
exit(1); return CLI_STATUS_ERROR;
} }
// Go quiet // Go quiet
@@ -170,6 +177,8 @@ static void daemonize(LOG_BACKEND log_backend, char *pid_file_path)
close(STDIN_FILENO); close(STDIN_FILENO);
close(STDERR_FILENO); close(STDERR_FILENO);
} }
return CLI_STATUS_OK;
} }
// Logs toxcore logger message using our logger facility // Logs toxcore logger message using our logger facility
@@ -212,11 +221,18 @@ int main(int argc, char *argv[])
char *cfg_file_path = nullptr; char *cfg_file_path = nullptr;
bool run_in_foreground = false; bool run_in_foreground = false;
// choose backend for printing command line argument parsing output based on whether the daemon is being run from a terminal // Choose backend for printing command line argument parsing output based on whether the daemon is being run from a terminal
LOG_BACKEND log_backend = isatty(STDOUT_FILENO) ? LOG_BACKEND_STDOUT : LOG_BACKEND_SYSLOG; LOG_BACKEND log_backend = isatty(STDOUT_FILENO) ? LOG_BACKEND_STDOUT : LOG_BACKEND_SYSLOG;
log_open(log_backend); log_open(log_backend);
handle_command_line_arguments(argc, argv, &cfg_file_path, &log_backend, &run_in_foreground); switch (handle_command_line_arguments(argc, argv, &cfg_file_path, &log_backend, &run_in_foreground)) {
case CLI_STATUS_OK:
break;
case CLI_STATUS_DONE:
return 0;
case CLI_STATUS_ERROR:
return 1;
}
log_close(); log_close();
log_open(log_backend); log_open(log_backend);
@@ -254,7 +270,14 @@ int main(int argc, char *argv[])
} }
if (!run_in_foreground) { if (!run_in_foreground) {
daemonize(log_backend, pid_file_path); switch (daemonize(log_backend, pid_file_path)) {
case CLI_STATUS_OK:
break;
case CLI_STATUS_DONE:
return 0;
case CLI_STATUS_ERROR:
return 1;
}
} }
free(pid_file_path); free(pid_file_path);

View File

@@ -12,6 +12,8 @@
#include <string.h> #include <string.h>
#include "../toxcore/network.h"
#define INFO_REQUEST_PACKET_LENGTH 78 #define INFO_REQUEST_PACKET_LENGTH 78
static uint32_t bootstrap_version; static uint32_t bootstrap_version;

View File

@@ -2,7 +2,8 @@
# autotools-linux # autotools-linux
FROM ubuntu:22.04 FROM ubuntu:22.04
RUN apt-get update && apt-get install --no-install-recommends -y \ RUN apt-get update && \
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
autoconf \ autoconf \
automake \ automake \
ca-certificates \ ca-certificates \

View File

@@ -7,6 +7,7 @@ RUN apt-get update && \
clang \ clang \
cmake \ cmake \
libconfig-dev \ libconfig-dev \
libgmock-dev \
libgtest-dev \ libgtest-dev \
libopus-dev \ libopus-dev \
libsodium-dev \ libsodium-dev \

View File

@@ -0,0 +1,21 @@
FROM alpine:3.19.0
RUN ["apk", "add", "--no-cache", \
"bash", \
"clang", \
"clang-extra-tools", \
"cmake", \
"colordiff", \
"libconfig-dev", \
"libsodium-dev", \
"libvpx-dev", \
"linux-headers", \
"opus-dev", \
"pkgconfig", \
"samurai"]
ENV CC=clang CXX=clang++
COPY . /c-toxcore/
WORKDIR /c-toxcore
RUN other/analysis/run-clang-tidy

View File

@@ -0,0 +1,5 @@
#!/bin/sh
set -eux
BUILD=clang-tidy
docker build -t "toxchat/c-toxcore:$BUILD" -f "other/docker/$BUILD/Dockerfile" .

View File

@@ -1,50 +1,57 @@
FROM toxchat/c-toxcore:sources AS src FROM toxchat/c-toxcore:sources AS src
FROM ubuntu:20.04 AS build FROM ubuntu:20.04 AS build
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN apt-get update && \ RUN apt-get update && \
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \ DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
ca-certificates \ ca-certificates \
clang \
cmake \
curl \ curl \
gcc \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-17 main" >> /etc/apt/sources.list \
&& curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc \
&& apt-get update && \
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
clang-17 \
cmake \
git \ git \
golang-1.18 \ golang-1.18 \
libclang-rt-17-dev \
libconfig-dev \ libconfig-dev \
libgmock-dev \
libgtest-dev \ libgtest-dev \
libopus-dev \ libopus-dev \
libsodium-dev \ libsodium-dev \
libunwind-17-dev \
libvpx-dev \ libvpx-dev \
llvm-dev \ lld-17 \
llvm-17-dev \
make \ make \
ninja-build \ ninja-build \
pkg-config \ pkg-config \
python3-pip \
python3-pygments \
&& apt-get clean \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/apt/lists/*
&& pip3 install --no-cache-dir gcovr
RUN ["strip", "-g",\
"/usr/lib/x86_64-linux-gnu/libgtest.a",\
"/usr/lib/x86_64-linux-gnu/libgtest_main.a"]
RUN ["curl", "-s", "https://codecov.io/bash", "-o", "/usr/local/bin/codecov"] RUN ["curl", "-s", "https://codecov.io/bash", "-o", "/usr/local/bin/codecov"]
RUN ["chmod", "+x", "/usr/local/bin/codecov"] RUN ["chmod", "+x", "/usr/local/bin/codecov"]
ENV CC=clang \ ENV CC=clang-17 \
CXX=clang++ \ CXX=clang++-17 \
PYTHONUNBUFFERED=1 \ PYTHONUNBUFFERED=1 \
PATH=$PATH:/usr/lib/go-1.18/bin PATH=$PATH:/usr/lib/go-1.18/bin
SHELL ["/bin/bash", "-c"]
COPY --from=src /src/ /work/
WORKDIR /work WORKDIR /work
COPY --from=src /src/ /work/ RUN git clone --depth=1 https://github.com/TokTok/toktok-fuzzer /work/testing/fuzzing/toktok-fuzzer
RUN source .github/scripts/flags-coverage.sh \ RUN source .github/scripts/flags-coverage.sh \
&& go version \ && go version \
&& (cd other/proxy && go get github.com/things-go/go-socks5 && go build proxy_server.go) \ && (cd other/proxy && go get github.com/things-go/go-socks5 && go build proxy_server.go) \
&& cmake -B_build -H. -GNinja \ && cmake -B_build -H. -GNinja \
-DCMAKE_C_FLAGS="$C_FLAGS" \ -DCMAKE_C_FLAGS="$C_FLAGS" \
-DCMAKE_CXX_FLAGS="$CXX_FLAGS" \ -DCMAKE_CXX_FLAGS="$CXX_FLAGS" \
-DCMAKE_EXE_LINKER_FLAGS="$LD_FLAGS" \ -DCMAKE_EXE_LINKER_FLAGS="$LD_FLAGS -fuse-ld=lld" \
-DCMAKE_UNITY_BUILD=ON \ -DCMAKE_UNITY_BUILD=ON \
-DENABLE_SHARED=OFF \ -DENABLE_SHARED=OFF \
-DMIN_LOGGER_LEVEL=TRACE \ -DMIN_LOGGER_LEVEL=TRACE \
@@ -53,6 +60,7 @@ RUN source .github/scripts/flags-coverage.sh \
-DSTRICT_ABI=ON \ -DSTRICT_ABI=ON \
-DAUTOTEST=ON \ -DAUTOTEST=ON \
-DPROXY_TEST=ON \ -DPROXY_TEST=ON \
-DBUILD_FUZZ_TESTS=ON \
-DUSE_IPV6=OFF \ -DUSE_IPV6=OFF \
-DTEST_TIMEOUT_SECONDS=40 \ -DTEST_TIMEOUT_SECONDS=40 \
&& cmake --build _build --parallel 8 --target install && cmake --build _build --parallel 8 --target install
@@ -63,24 +71,15 @@ RUN /work/other/proxy/proxy_server \
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6) ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6)
WORKDIR /work/mallocfail WORKDIR /work/mallocfail
RUN ["git", "clone", "--depth=1", "https://github.com/ralight/mallocfail", "/work/mallocfail"] RUN ["git", "clone", "--depth=1", "https://github.com/TokTok/mallocfail", "/work/mallocfail"]
COPY other/docker/coverage/syscall_funcs.c src/ RUN clang-17 -fuse-ld=lld -fPIC -shared -O2 -g3 -Wall -I/usr/lib/llvm-17/include -L/usr/lib/llvm-17/lib -Ideps/uthash -Ideps/sha3 deps/*/*.c src/*.c -o mallocfail.so -ldl -lunwind \
RUN gcc -fPIC -shared -O2 -g3 -Wall -Ideps/uthash -Ideps/sha3 deps/*/*.c src/*.c -o mallocfail.so -ldl -lbacktrace \
&& install mallocfail.so /usr/local/lib/mallocfail.so && install mallocfail.so /usr/local/lib/mallocfail.so
WORKDIR /work/_build WORKDIR /work/_build
COPY other/docker/coverage/run_mallocfail /usr/local/bin/ COPY other/docker/coverage/run_mallocfail /usr/local/bin/
RUN ["run_mallocfail", "--ctest=2", "--jobs=8"] RUN ["run_mallocfail", "--ctest=1", "--jobs=8"]
RUN ["gcovr", \ RUN llvm-profdata-17 merge -sparse $(find . -name "*.profraw") -o toxcore.profdata
"--sort-percentage", \ RUN llvm-cov-17 show -format=text -instr-profile=toxcore.profdata -sources $(cmake --build . --target help | grep -o '[^:]*_test:' | grep -o '[^:]*' | xargs -n1 find . -type f -name | awk '{print "-object "$1}') > coverage.txt
"--gcov-executable=llvm-cov gcov", \ RUN llvm-cov-17 show -format=html -instr-profile=toxcore.profdata -sources $(cmake --build . --target help | grep -o '[^:]*_test:' | grep -o '[^:]*' | xargs -n1 find . -type f -name | awk '{print "-object "$1}') -output-dir=html
"--html-details=html/", \
"--root=..", \
"--exclude=CMakeFiles/", \
"--exclude=_deps/", \
"--exclude=(.+/)?auto_tests/", \
"--exclude=.+_test.cc?$", \
"--exclude=(.+/)?other/", \
"--exclude=(.+/)?testing/"]
WORKDIR /work WORKDIR /work

View File

@@ -1,5 +1,4 @@
# vim:ft=dockerfile # vim:ft=dockerfile
FROM toxchat/c-toxcore:coverage AS build FROM toxchat/c-toxcore:coverage AS build
FROM nginx:alpine FROM nginx:alpine
COPY --from=build /work/_build/html/coverage_details.html /usr/share/nginx/html/index.html COPY --from=build --chown=nginx:nginx /work/_build/html/ /usr/share/nginx/html/
COPY --from=build /work/_build/html/ /usr/share/nginx/html/

View File

@@ -6,4 +6,4 @@ read -a ci_env <<<"$(bash <(curl -s https://codecov.io/env))"
docker build -t toxchat/c-toxcore:sources -f other/docker/sources/Dockerfile . docker build -t toxchat/c-toxcore:sources -f other/docker/sources/Dockerfile .
docker build -t toxchat/c-toxcore:coverage -f other/docker/coverage/Dockerfile . docker build -t toxchat/c-toxcore:coverage -f other/docker/coverage/Dockerfile .
docker run "${ci_env[@]}" -e CI=true --name toxcore-coverage --rm -t toxchat/c-toxcore:coverage /usr/local/bin/codecov -x "llvm-cov gcov" docker run "${ci_env[@]}" -e CI=true --name toxcore-coverage --rm -t toxchat/c-toxcore:coverage /usr/local/bin/codecov

View File

@@ -27,11 +27,12 @@ from typing import NoReturn
from typing import Optional from typing import Optional
from typing import Tuple from typing import Tuple
_PRIMER = "./unit_util_test" _PRIMER = "auto_tests/auto_version_test"
_MALLOCFAIL_SO = "/usr/local/lib/mallocfail.so" _MALLOCFAIL_SO = "/usr/local/lib/mallocfail.so"
_HASHES = "mallocfail_hashes" _HASHES = "mallocfail_hashes"
_HASHES_PREV = "mallocfail_hashes.prev" _HASHES_PREV = "mallocfail_hashes.prev"
_TIMEOUT = 3.0 _TIMEOUT = 3.0
_BUILD_DIR = os.getcwd()
_ENV = { _ENV = {
"LD_PRELOAD": _MALLOCFAIL_SO, "LD_PRELOAD": _MALLOCFAIL_SO,
@@ -45,10 +46,19 @@ def run_mallocfail(tmpdir: str, timeout: float, exe: str, iteration: int,
print(f"\x1b[1;33mmallocfail '{exe}' run #{iteration}\x1b[0m") print(f"\x1b[1;33mmallocfail '{exe}' run #{iteration}\x1b[0m")
hashes = os.path.join(tmpdir, _HASHES) hashes = os.path.join(tmpdir, _HASHES)
hashes_prev = os.path.join(tmpdir, _HASHES_PREV) hashes_prev = os.path.join(tmpdir, _HASHES_PREV)
profraw = os.path.join(_BUILD_DIR, "mallocfail.out", exe, "%p.profraw")
if os.path.exists(hashes): if os.path.exists(hashes):
shutil.copy(hashes, hashes_prev) shutil.copy(hashes, hashes_prev)
try: try:
proc = subprocess.run([exe], timeout=timeout, env=_ENV, cwd=tmpdir) proc = subprocess.run(
[exe],
timeout=timeout,
env={
"LLVM_PROFILE_FILE": profraw,
**_ENV,
},
cwd=tmpdir,
)
except subprocess.TimeoutExpired: except subprocess.TimeoutExpired:
print(f"\x1b[1;34mProgram {exe} timed out\x1b[0m") print(f"\x1b[1;34mProgram {exe} timed out\x1b[0m")
return True return True
@@ -65,13 +75,16 @@ def run_mallocfail(tmpdir: str, timeout: float, exe: str, iteration: int,
# Process exited cleanly (success or failure). # Process exited cleanly (success or failure).
pass pass
elif proc.returncode == -6: elif proc.returncode == -6:
# Assertion failed. # abort(), we allow it.
pass
elif proc.returncode == 7:
# ck_assert failed, also fine for us.
pass pass
elif proc.returncode == -14: elif proc.returncode == -14:
print(f"\x1b[0;34mProgram '{exe}' timed out\x1b[0m") print(f"\x1b[0;34mProgram '{exe}' timed out\x1b[0m")
else: else:
print( print(
f"\x1b[1;32mProgram '{exe}' failed to handle OOM situation cleanly\x1b[0m" f"\x1b[1;32mProgram '{exe}' failed to handle OOM situation cleanly (code {proc.returncode})\x1b[0m"
) )
if not keep_going: if not keep_going:
raise Exception("Aborting test") raise Exception("Aborting test")
@@ -96,8 +109,8 @@ def find_prog(name: str) -> Tuple[Optional[str], ...]:
return path return path
return None return None
return (attempt(f"./unit_{name}_test"), return (attempt(f"auto_tests/auto_{name}_test"),
attempt(f"auto_tests/auto_{name}_test")) ) # attempt(f"./unit_{name}_test"),
def parse_flags(args: List[str]) -> Tuple[Dict[str, str], List[str]]: def parse_flags(args: List[str]) -> Tuple[Dict[str, str], List[str]]:
@@ -128,6 +141,9 @@ def isolated_mallocfail(timeout: int, exe: str) -> None:
shutil.copy(exe, os.path.join(tmpdir, exe)) shutil.copy(exe, os.path.join(tmpdir, exe))
shutil.copy(_HASHES, os.path.join(tmpdir, _HASHES)) shutil.copy(_HASHES, os.path.join(tmpdir, _HASHES))
loop_mallocfail(tmpdir, timeout, exe) loop_mallocfail(tmpdir, timeout, exe)
profraw = os.path.join(tmpdir, "default.profraw")
if os.path.exists(profraw):
shutil.copy(profraw, exe + ".mallocfail.profraw")
def main(args: List[str]) -> None: def main(args: List[str]) -> None:
@@ -150,12 +166,12 @@ def main(args: List[str]) -> None:
else: else:
jobs = 1 jobs = 1
# Start by running util_test, which allocates no memory of its own, just # Start by running version_test, which allocates no memory of its own, just
# to prime the mallocfail hashes so it doesn't make global initialisers # to prime the mallocfail hashes so it doesn't make global initialisers
# such as llvm_gcov_init fail. # such as llvm_gcov_init fail.
if os.path.exists(_PRIMER): if os.path.exists(_PRIMER):
print(f"\x1b[1;33mPriming hashes with unit_util_test\x1b[0m") print(f"\x1b[1;33mPriming hashes with {_PRIMER}\x1b[0m")
loop_mallocfail(".", timeout, _PRIMER, keep_going=True) loop_mallocfail(os.getcwd(), timeout, _PRIMER, keep_going=True)
print(f"\x1b[1;33m--------------------------------\x1b[0m") print(f"\x1b[1;33m--------------------------------\x1b[0m")
print(f"\x1b[1;33mStarting mallocfail for {len(exes)} programs:\x1b[0m") print(f"\x1b[1;33mStarting mallocfail for {len(exes)} programs:\x1b[0m")

View File

@@ -1,149 +0,0 @@
#define _GNU_SOURCE
#include "mallocfail.h"
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
static int (*libc_ioctl)(int fd, unsigned long request, ...);
static int (*libc_bind)(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
static int (*libc_getsockopt)(int sockfd, int level, int optname,
void *optval, socklen_t *optlen);
static int (*libc_setsockopt)(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
static ssize_t (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
static ssize_t (*libc_recvfrom)(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
static ssize_t (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
static ssize_t(*libc_sendto)(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
static int (*libc_socket)(int domain, int type, int protocol);
static int (*libc_listen)(int sockfd, int backlog);
__attribute__((__constructor__))
static void init(void)
{
libc_ioctl = dlsym(RTLD_NEXT, "ioctl");
libc_bind = dlsym(RTLD_NEXT, "bind");
libc_getsockopt = dlsym(RTLD_NEXT, "getsockopt");
libc_setsockopt = dlsym(RTLD_NEXT, "setsockopt");
libc_recv = dlsym(RTLD_NEXT, "recv");
libc_recvfrom = dlsym(RTLD_NEXT, "recvfrom");
libc_send = dlsym(RTLD_NEXT, "send");
libc_sendto = dlsym(RTLD_NEXT, "sendto");
libc_socket = dlsym(RTLD_NEXT, "socket");
libc_listen = dlsym(RTLD_NEXT, "listen");
}
int ioctl(int fd, unsigned long request, ...)
{
if (should_malloc_fail()) {
errno = ENOMEM;
return -1;
}
va_list ap;
va_start(ap, request);
const int ret = libc_ioctl(fd, SIOCGIFCONF, va_arg(ap, void *));
va_end(ap);
return ret;
}
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen)
{
// Unlike all others, if bind should fail once, it should fail always, because in toxcore we try
// many ports before giving up. If this only fails once, we'll never reach the code path where
// we give up.
static int should_fail = -1;
if (should_fail == -1) {
should_fail = should_malloc_fail();
}
if (should_fail) {
errno = ENOMEM;
return -1;
}
return libc_bind(sockfd, addr, addrlen);
}
int getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen)
{
if (should_malloc_fail()) {
errno = ENOMEM;
return -1;
}
return libc_getsockopt(sockfd, level, optname, optval, optlen);
}
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen)
{
if (should_malloc_fail()) {
errno = ENOMEM;
return -1;
}
return libc_setsockopt(sockfd, level, optname, optval, optlen);
}
ssize_t recv(int sockfd, void *buf, size_t len, int flags)
{
if (should_malloc_fail()) {
errno = ENOMEM;
return -1;
}
return libc_recv(sockfd, buf, len, flags);
}
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
{
if (should_malloc_fail()) {
errno = ENOMEM;
return -1;
}
return libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
}
ssize_t send(int sockfd, const void *buf, size_t len, int flags)
{
if (should_malloc_fail()) {
errno = ENOMEM;
return -1;
}
return libc_send(sockfd, buf, len, flags);
}
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen)
{
if (should_malloc_fail()) {
errno = ENOMEM;
return -1;
}
return libc_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}
int socket(int domain, int type, int protocol)
{
if (should_malloc_fail()) {
errno = ENOMEM;
return -1;
}
return libc_socket(domain, type, protocol);
}
int listen(int sockfd, int backlog)
{
if (should_malloc_fail()) {
errno = ENOMEM;
return -1;
}
return libc_listen(sockfd, backlog);
}

View File

@@ -92,6 +92,10 @@
<alloc init="true">new_networking_no_udp</alloc> <alloc init="true">new_networking_no_udp</alloc>
<dealloc arg="1">kill_networking</dealloc> <dealloc arg="1">kill_networking</dealloc>
</resource> </resource>
<resource>
<alloc init="true">net_new_strerror</alloc>
<dealloc arg="1">net_kill_strerror</dealloc>
</resource>
<resource> <resource>
<alloc init="true">new_onion</alloc> <alloc init="true">new_onion</alloc>
<dealloc arg="1">kill_onion</dealloc> <dealloc arg="1">kill_onion</dealloc>

View File

@@ -5,7 +5,7 @@ ENV LANG=en_US.UTF-8 \
LC_CTYPE=en_US.UTF-8 \ LC_CTYPE=en_US.UTF-8 \
LC_ALL=en_US.UTF-8 LC_ALL=en_US.UTF-8
RUN apk add --no-cache doxygen git graphviz \ RUN apk add --no-cache doxygen git graphviz texlive \
&& git clone --depth=1 https://github.com/jothepro/doxygen-awesome-css.git /work/doxygen-awesome-css && git clone --depth=1 https://github.com/jothepro/doxygen-awesome-css.git /work/doxygen-awesome-css
WORKDIR /work WORKDIR /work
COPY . /work/ COPY . /work/

View File

@@ -0,0 +1,41 @@
FROM toxchat/infer:latest
COPY toxav/ /work/c-toxcore/toxav/
COPY toxcore/ /work/c-toxcore/toxcore/
COPY toxencryptsave/ /work/c-toxcore/toxencryptsave/
COPY third_party/ /work/c-toxcore/third_party/
RUN infer capture -- clang++ -fsyntax-only \
$(pkg-config --cflags libconfig libsodium opus vpx) \
/work/c-toxcore/toxav/*.c \
/work/c-toxcore/toxcore/*.c \
/work/c-toxcore/toxcore/*/*.c \
/work/c-toxcore/toxencryptsave/*.c
RUN ["infer", "analyze",\
"--report-console-limit", "100",\
"--jobs", "8",\
"--no-bufferoverrun",\
"--no-datalog",\
"--print-active-checkers",\
"--loop-hoisting",\
"--quandary",\
"--racerd",\
"--starvation",\
"--uninit",\
"--disable-issue-type", "BUFFER_OVERRUN_L2",\
"--disable-issue-type", "PULSE_UNNECESSARY_COPY",\
"--enable-issue-type", "EXPENSIVE_EXECUTION_TIME",\
"--enable-issue-type", "INVARIANT_CALL",\
"--enable-issue-type", "PULSE_UNINITIALIZED_CONST",\
"--enable-issue-type", "SENSITIVE_DATA_FLOW",\
"--enable-issue-type", "UNTRUSTED_BUFFER_ACCESS",\
"--enable-issue-type", "UNTRUSTED_HEAP_ALLOCATION",\
"--disable-issue-type", "USE_AFTER_FREE_LATENT",\
"--disable-issue-type", "STACK_VARIABLE_ADDRESS_ESCAPE",\
"--disable-issue-type", "INVARIANT_CALL",\
"--fail-on-issue"]
# In the above, the first 2 are disabled for extreme sensitivity and false
# positives, the ones at the end are probably decent, but have some false
# positives, so we can't fail-on-issue with them on.
# INVARIANT_CALL is pretty fun, but currently wrong, because it can't see
# through potential mutations via callbacks. Our code is bad and we should
# feel bad, but until that's fixed, the invariant checker doesn't work.

View File

@@ -0,0 +1,5 @@
#!/bin/sh
set -eux
BUILD=infer
docker build -t "toxchat/c-toxcore:$BUILD" -f "other/docker/$BUILD/Dockerfile" .

View File

@@ -1,6 +1,7 @@
FROM ubuntu:20.04 FROM ubuntu:20.04
RUN apt-get update && apt-get install --no-install-recommends -y \ RUN apt-get update && \
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
ca-certificates \ ca-certificates \
cppcheck \ cppcheck \
libopus-dev \ libopus-dev \

View File

@@ -1,7 +1,8 @@
FROM toxchat/haskell:hs-tokstyle AS tokstyle FROM toxchat/haskell:hs-tokstyle AS tokstyle
FROM ubuntu:22.04 FROM ubuntu:22.04
RUN apt-get update && apt-get install --no-install-recommends -y \ RUN apt-get update && \
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
ca-certificates \ ca-certificates \
clang \ clang \
git \ git \

View File

@@ -2,7 +2,7 @@ FROM debian:bullseye-slim
# Build-time environment variables # Build-time environment variables
ARG VERSION_MSGPACK=4.0.0 \ ARG VERSION_MSGPACK=4.0.0 \
VERSION_SODIUM=1.0.18 \ VERSION_SODIUM=1.0.19 \
VERSION_OPUS=1.3.1 \ VERSION_OPUS=1.3.1 \
VERSION_VPX=1.11.0 \ VERSION_VPX=1.11.0 \
\ \

View File

@@ -40,9 +40,9 @@ build() {
echo echo
echo "=== Building Sodium $VERSION_SODIUM $ARCH ===" echo "=== Building Sodium $VERSION_SODIUM $ARCH ==="
curl "${CURL_OPTIONS[@]}" -O "https://download.libsodium.org/libsodium/releases/libsodium-$VERSION_SODIUM.tar.gz" curl "${CURL_OPTIONS[@]}" -O "https://github.com/jedisct1/libsodium/releases/download/$VERSION_SODIUM-RELEASE/libsodium-$VERSION_SODIUM.tar.gz"
tar -xf "libsodium-$VERSION_SODIUM.tar.gz" tar -xf "libsodium-$VERSION_SODIUM.tar.gz"
cd "libsodium-$VERSION_SODIUM" cd "libsodium-stable"
./configure --host="$WINDOWS_TOOLCHAIN" --prefix="$PREFIX_DIR" --disable-shared --enable-static ./configure --host="$WINDOWS_TOOLCHAIN" --prefix="$PREFIX_DIR" --disable-shared --enable-static
make make
make install make install

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// Copyright © 2023 The TokTok team. // Copyright © 2023-2024 The TokTok team.
// this file can be used to generate event.c files // this file can be used to generate event.c files
// requires c++17 // requires c++17
@@ -56,15 +56,31 @@ std::string bin_pack_name_from_type(const std::string& type) {
return "bin_pack_u8"; return "bin_pack_u8";
} else if (type == "bool") { } else if (type == "bool") {
return "bin_pack_bool"; return "bin_pack_bool";
// only unpack is special TODO(Green-Sky): should we change that? } else if (type == "Tox_User_Status") {
//} else if (type == "Tox_User_Status") { return "tox_user_status_pack";
//return "tox_pack_user_status"; } else if (type == "Tox_Conference_Type") {
//} else if (type == "Tox_Conference_Type") { return "tox_conference_type_pack";
//return "tox_pack_conference_type"; } else if (type == "Tox_Message_Type") {
return "tox_message_type_pack";
} else if (type == "Tox_File_Control") {
return "tox_file_control_pack";
} else if (type == "Tox_Connection") {
return "tox_connection_pack";
} else if (type == "Tox_Group_Privacy_State") {
return "tox_group_privacy_state_pack";
} else if (type == "Tox_Group_Voice_State") {
return "tox_group_voice_state_pack";
} else if (type == "Tox_Group_Topic_Lock") {
return "tox_group_topic_lock_pack";
} else if (type == "Tox_Group_Join_Fail") {
return "tox_group_join_fail_pack";
} else if (type == "Tox_Group_Mod_Event") {
return "tox_group_mod_event_pack";
} else if (type == "Tox_Group_Exit_Type") {
return "tox_group_exit_type_pack";
} else { } else {
//std::cerr << "unknown type " << type << "\n"; std::cerr << "unknown type " << type << "\n";
//exit(1); exit(1);
// assume enum -> u32
return "bin_pack_u32"; return "bin_pack_u32";
} }
} }
@@ -119,22 +135,55 @@ void generate_event_impl(const std::string& event_name, const std::vector<EventT
exit(1); exit(1);
} }
bool need_stdlib_h = false;
bool need_string_h = false;
bool need_tox_unpack_h = false;
for (const auto& t : event_types) {
std::visit(
overloaded{
[&](const EventTypeTrivial& t) {
if (bin_unpack_name_from_type(t.type).rfind("tox_", 0) == 0) {
need_tox_unpack_h = true;
}
},
[&](const EventTypeByteRange&) {
need_stdlib_h = true;
need_string_h = true;
}
},
t
);
}
f << R"(/* SPDX-License-Identifier: GPL-3.0-or-later f << R"(/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2023 The TokTok team. * Copyright © 2023-2024 The TokTok team.
*/ */
#include "events_alloc.h" #include "events_alloc.h"
#include <assert.h> #include <assert.h>)";
#include <stdlib.h> if (need_stdlib_h) {
#include <string.h> f << R"(
#include <stdlib.h>)";
}
if (need_string_h) {
f << R"(
#include <string.h>)";
}
f << R"(
#include "../bin_pack.h" #include "../bin_pack.h"
#include "../bin_unpack.h" #include "../bin_unpack.h"
#include "../ccompat.h" #include "../ccompat.h"
#include "../mem.h"
#include "../tox.h" #include "../tox.h"
#include "../tox_events.h" #include "../tox_events.h")";
#include "../tox_unpack.h" if (need_tox_unpack_h) {
f << R"(
#include "../tox_pack.h"
#include "../tox_unpack.h")";
}
f << R"(
/***************************************************** /*****************************************************
@@ -205,10 +254,11 @@ void generate_event_impl(const std::string& event_name, const std::vector<EventT
f << " " << event_name_l << "->" << t.name_data << " = nullptr;\n"; f << " " << event_name_l << "->" << t.name_data << " = nullptr;\n";
f << " " << event_name_l << "->" << t.name_length << " = 0;\n"; f << " " << event_name_l << "->" << t.name_length << " = 0;\n";
f << " }\n\n"; f << " }\n\n";
f << " " << event_name_l << "->" << t.name_data << " = (uint8_t *)malloc(" << t.name_length << ");\n\n"; f << " uint8_t *" << t.name_data << "_copy = (uint8_t *)malloc(" << t.name_length << ");\n\n";
f << " if (" << event_name_l << "->" << t.name_data << " == nullptr) {\n"; f << " if (" << t.name_data << "_copy == nullptr) {\n";
f << " return false;\n }\n\n"; f << " return false;\n }\n\n";
f << " memcpy(" << event_name_l << "->" << t.name_data << ", " << t.name_data << ", " << t.name_length << ");\n"; f << " memcpy(" << t.name_data << "_copy, " << t.name_data << ", " << t.name_length << ");\n";
f << " " << event_name_l << "->" << t.name_data << " = " << t.name_data << "_copy;\n";
f << " " << event_name_l << "->" << t.name_length << " = " << t.name_length << ";\n"; f << " " << event_name_l << "->" << t.name_length << " = " << t.name_length << ";\n";
f << " return true;\n"; f << " return true;\n";
} }
@@ -277,20 +327,30 @@ void generate_event_impl(const std::string& event_name, const std::vector<EventT
// pack // pack
f << "bool tox_event_" << event_name_l << "_pack(\n"; f << "bool tox_event_" << event_name_l << "_pack(\n";
f << " const Tox_Event_" << event_name << " *event, Bin_Pack *bp)\n{\n"; f << " const Tox_Event_" << event_name << " *event, Bin_Pack *bp)\n{\n";
f << " assert(event != nullptr);\n";
f << " return bin_pack_array(bp, 2)\n"; bool return_started = false;
f << " && bin_pack_u32(bp, TOX_EVENT_" << str_toupper(event_name) << ")";
if (event_types.size() > 1) { if (event_types.size() > 1) {
f << "\n && bin_pack_array(bp, " << event_types.size() << ")"; f << " return bin_pack_array(bp, " << event_types.size() << ")";
return_started = true;
} }
for (const auto& t : event_types) { for (const auto& t : event_types) {
f << "\n && "; if (return_started) {
f << "\n && ";
} else {
f << " return ";
}
std::visit( std::visit(
overloaded{ overloaded{
[&](const EventTypeTrivial& t) { [&](const EventTypeTrivial& t) {
f << bin_pack_name_from_type(t.type); f << bin_pack_name_from_type(t.type);
f << "(bp, event->" << t.name << ")"; if (t.type.rfind("Tox_", 0) == 0) {
f << "(event->" << t.name << ", bp)";
} else {
f << "(bp, event->" << t.name << ")";
}
}, },
[&](const EventTypeByteRange& t) { [&](const EventTypeByteRange& t) {
f << "bin_pack_bin(bp, event->" << t.name_data << ", event->" << t.name_length << ")"; f << "bin_pack_bin(bp, event->" << t.name_data << ", event->" << t.name_length << ")";
@@ -321,7 +381,11 @@ void generate_event_impl(const std::string& event_name, const std::vector<EventT
overloaded{ overloaded{
[&](const EventTypeTrivial& t) { [&](const EventTypeTrivial& t) {
f << bin_unpack_name_from_type(t.type); f << bin_unpack_name_from_type(t.type);
f << "(bu, &event->" << t.name << ")"; if (t.type.rfind("Tox_", 0) == 0) {
f << "(&event->" << t.name << ", bu)";
} else {
f << "(bu, &event->" << t.name << ")";
}
}, },
[&](const EventTypeByteRange& t) { [&](const EventTypeByteRange& t) {
f << "bin_unpack_bin(bu, &event->" << t.name_data << ", &event->" << t.name_length << ")"; f << "bin_unpack_bin(bu, &event->" << t.name_data << ", &event->" << t.name_length << ")";
@@ -371,28 +435,6 @@ void generate_event_impl(const std::string& event_name, const std::vector<EventT
f << " tox_events_add(events, &event);\n"; f << " tox_events_add(events, &event);\n";
f << " return " << event_name_l << ";\n}\n\n"; f << " return " << event_name_l << ";\n}\n\n";
// get
f << "const Tox_Event_" << event_name << " *tox_events_get_" << event_name_l << "(const Tox_Events *events, uint32_t index)\n{\n";
f << " uint32_t " << event_name_l << "_index = 0;\n";
f << " const uint32_t size = tox_events_get_size(events);\n\n";
f << " for (uint32_t i = 0; i < size; ++i) {\n";
f << " if (" << event_name_l << "_index > index) {\n";
f << " return nullptr;\n }\n\n";
f << " if (events->events[i].type == TOX_EVENT_" << str_toupper(event_name) << ") {\n";
f << " const Tox_Event_" << event_name << " *" << event_name_l << " = events->events[i].data." << event_name_l << ";\n";
f << " if (" << event_name_l << "_index == index) {\n";
f << " return " << event_name_l << ";\n }\n";
f << " ++" << event_name_l << "_index;\n }\n }\n\n return nullptr;\n}\n\n";
// get size
f << "uint32_t tox_events_get_" << event_name_l << "_size(const Tox_Events *events)\n{\n";
f << " uint32_t " << event_name_l << "_size = 0;\n";
f << " const uint32_t size = tox_events_get_size(events);\n\n";
f << " for (uint32_t i = 0; i < size; ++i) {\n";
f << " if (events->events[i].type == TOX_EVENT_" << str_toupper(event_name) << ") {\n";
f << " ++" << event_name_l << "_size;\n }\n }\n\n";
f << " return " << event_name_l << "_size;\n}\n\n";
// unpack // unpack
f << "bool tox_event_" << event_name_l << "_unpack(\n"; f << "bool tox_event_" << event_name_l << "_unpack(\n";
f << " Tox_Event_" << event_name << " **event, Bin_Unpack *bu, const Memory *mem)\n{\n"; f << " Tox_Event_" << event_name << " **event, Bin_Unpack *bu, const Memory *mem)\n{\n";

View File

@@ -10,3 +10,6 @@ sonar.sources=.
# Encoding of the source code. # Encoding of the source code.
sonar.sourceEncoding=UTF-8 sonar.sourceEncoding=UTF-8
# More precise Python version.
sonar.python.version=3.11

View File

@@ -13,7 +13,6 @@ sh_test(
args = ["$(locations %s)" % f for f in CIMPLE_FILES] + [ args = ["$(locations %s)" % f for f in CIMPLE_FILES] + [
"-Wno-boolean-return", "-Wno-boolean-return",
"-Wno-callback-names", "-Wno-callback-names",
"-Wno-enum-names",
"+RTS", "+RTS",
"-N4", "-N4",
"-RTS", "-RTS",

View File

@@ -8,10 +8,19 @@ if(TARGET toxcore_static)
else() else()
target_link_libraries(misc_tools PRIVATE toxcore_shared) target_link_libraries(misc_tools PRIVATE toxcore_shared)
endif() endif()
target_link_libraries(misc_tools PRIVATE ${LIBSODIUM_LIBRARIES}) if(TARGET unofficial-sodium::sodium)
target_link_directories(misc_tools PUBLIC ${LIBSODIUM_LIBRARY_DIRS}) target_link_libraries(misc_tools PRIVATE unofficial-sodium::sodium)
target_include_directories(misc_tools SYSTEM PRIVATE ${LIBSODIUM_INCLUDE_DIRS}) else()
target_compile_options(misc_tools PRIVATE ${LIBSODIUM_CFLAGS_OTHER}) target_link_libraries(misc_tools PRIVATE ${LIBSODIUM_LIBRARIES})
target_link_directories(misc_tools PUBLIC ${LIBSODIUM_LIBRARY_DIRS})
target_include_directories(misc_tools SYSTEM PRIVATE ${LIBSODIUM_INCLUDE_DIRS})
target_compile_options(misc_tools PRIVATE ${LIBSODIUM_CFLAGS_OTHER})
endif()
if(TARGET PThreads4W::PThreads4W)
target_link_libraries(misc_tools PRIVATE PThreads4W::PThreads4W)
elseif(TARGET Threads::Threads)
target_link_libraries(misc_tools PRIVATE Threads::Threads)
endif()
################################################################################ ################################################################################
# #
@@ -27,4 +36,9 @@ if(BUILD_MISC_TESTS)
else() else()
target_link_libraries(Messenger_test PRIVATE toxcore_shared) target_link_libraries(Messenger_test PRIVATE toxcore_shared)
endif() endif()
if(TARGET PThreads4W::PThreads4W)
target_link_libraries(Messenger_test PRIVATE PThreads4W::PThreads4W)
elseif(TARGET Threads::Threads)
target_link_libraries(Messenger_test PRIVATE Threads::Threads)
endif()
endif() endif()

View File

@@ -4,4 +4,4 @@
cd ../ cd ../
# Run code coverage only on minized corpus to save time # Run code coverage only on minized corpus to save time
afl-cov --cover-corpus -d ./_afl_out --overwrite --live --coverage-cmd "_cov_build/bootstrap_fuzzer @@" --code-dir ../ afl-cov --cover-corpus -d ./_afl_out --overwrite --live --coverage-cmd "_cov_build/bootstrap_fuzz_test @@" --code-dir ../

View File

@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
HARNESS_BIN="../_afl_build/bootstrap_fuzzer" HARNESS_BIN="../_afl_build/bootstrap_fuzz_test"
COV_BIN="../_cov_build/bootstrap_fuzzer" COV_BIN="../_cov_build/bootstrap_fuzz_test"
# move to repo root # move to repo root
cd ../ cd ../

View File

@@ -1,6 +1,5 @@
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test") load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test")
load("@rules_fuzzing//fuzzing/private:binary.bzl", "fuzzing_binary") # buildifier: disable=bzl-visibility
cc_library( cc_library(
name = "fuzz_support", name = "fuzz_support",
@@ -27,9 +26,9 @@ cc_library(
cc_fuzz_test( cc_fuzz_test(
name = "bootstrap_fuzz_test", name = "bootstrap_fuzz_test",
size = "small", size = "small",
srcs = ["bootstrap_harness.cc"], srcs = ["bootstrap_fuzz_test.cc"],
copts = ["-UNDEBUG"], copts = ["-UNDEBUG"],
corpus = ["//tools/toktok-fuzzer/corpus:bootstrap_fuzzer"], corpus = ["//tools/toktok-fuzzer/corpus:bootstrap_fuzz_test"],
deps = [ deps = [
":fuzz_support", ":fuzz_support",
":fuzz_tox", ":fuzz_tox",
@@ -58,9 +57,9 @@ cc_fuzz_test(
cc_fuzz_test( cc_fuzz_test(
name = "toxsave_fuzz_test", name = "toxsave_fuzz_test",
size = "small", size = "small",
srcs = ["toxsave_harness.cc"], srcs = ["toxsave_fuzz_test.cc"],
copts = ["-UNDEBUG"], copts = ["-UNDEBUG"],
corpus = ["//tools/toktok-fuzzer/corpus:toxsave_fuzzer"], corpus = ["//tools/toktok-fuzzer/corpus:toxsave_fuzz_test"],
deps = [ deps = [
":fuzz_support", ":fuzz_support",
"//c-toxcore/toxcore:tox", "//c-toxcore/toxcore:tox",
@@ -80,12 +79,34 @@ cc_binary(
], ],
) )
fuzzing_binary( genrule(
name = "protodump_bin", name = "e2e_fuzz_test_init",
testonly = True, outs = [
binary = ":protodump", "e2e_fuzz_test_init.dat",
engine = "@rules_fuzzing//fuzzing:cc_engine", "e2e_fuzz_test_bootstrap.dat",
],
cmd = "$(location :protodump) $(location e2e_fuzz_test_init.dat) $(location e2e_fuzz_test_bootstrap.dat)",
tags = ["manual"], tags = ["manual"],
tools = [":protodump"],
)
# bazel test --config=asan-libfuzzer //c-toxcore/testing/fuzzing:protodump_reduce_test
cc_test(
name = "protodump_reduce_test",
size = "small",
srcs = ["protodump_reduce.cc"],
args = ["$(location :e2e_fuzz_test_init.dat)"],
copts = ["-UNDEBUG"],
data = [":e2e_fuzz_test_init.dat"],
tags = ["manual"],
deps = [
":fuzz_support",
":fuzz_tox",
"//c-toxcore/toxcore:tox",
"//c-toxcore/toxcore:tox_dispatch",
"//c-toxcore/toxcore:tox_events",
"@rules_fuzzing//fuzzing:cc_engine",
],
) )
cc_fuzz_test( cc_fuzz_test(

View File

@@ -1,26 +1,29 @@
# For coverage tests
target_compile_definitions(toxcore_static PUBLIC "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION")
# Override network and random functions # Override network and random functions
add_library(fuzz_support func_conversion.h fuzz_support.cc fuzz_support.h) add_library(fuzz_support func_conversion.h fuzz_support.cc fuzz_support.h)
set(LIBFUZZER_LINKER_FLAGS) set(LIBFUZZER_LINKER_FLAGS)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(LIBFUZZER_LINKER_FLAGS "-fsanitize=fuzzer") set(LIBFUZZER_LINKER_FLAGS "-fsanitize=fuzzer")
else() else()
message(SEND_ERROR "Compiler must be Clang to build fuzz targets") message(SEND_ERROR "Compiler must be Clang to build fuzz targets")
endif() endif()
# Fuzzes the toxsave API function(fuzz_test target source_dir)
add_executable(toxsave_fuzzer toxsave_harness.cc) set(CORPUS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/toktok-fuzzer/corpus/${target}_fuzz_test)
target_link_libraries(toxsave_fuzzer PRIVATE toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS}) file(GLOB CORPUS "${CORPUS_DIR}/*")
add_executable(${target}_fuzz_test ${source_dir}/${target}_fuzz_test.cc)
target_link_libraries(${target}_fuzz_test PRIVATE fuzz_support test_util toxcore_fuzz ${LIBFUZZER_LINKER_FLAGS})
if(CORPUS)
add_test(NAME ${target}_fuzz COMMAND ${CROSSCOMPILING_EMULATOR} ${target}_fuzz_test -max_total_time=10 ${CORPUS})
set_property(TEST ${target}_fuzz PROPERTY ENVIRONMENT "LLVM_PROFILE_FILE=${target}.profraw;srcdir=${CMAKE_CURRENT_SOURCE_DIR}")
endif()
endfunction()
# Fuzzes the bootstrap process fuzz_test(bootstrap .) # Fuzzes the bootstrap process
add_executable(bootstrap_fuzzer bootstrap_harness.cc) fuzz_test(toxsave .) # Fuzzes the bootstrap process
target_link_libraries(bootstrap_fuzzer PRIVATE toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS})
add_executable(DHT_fuzz_test ../../toxcore/DHT_fuzz_test.cc) fuzz_test(DHT ../../toxcore)
target_link_libraries(DHT_fuzz_test PRIVATE toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS}) fuzz_test(forwarding ../../toxcore)
fuzz_test(group_announce ../../toxcore)
add_executable(tox_events_fuzz_test ../../toxcore/tox_events_fuzz_test.cc) fuzz_test(group_moderation ../../toxcore)
target_link_libraries(tox_events_fuzz_test PRIVATE toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS}) fuzz_test(tox_events ../../toxcore)

View File

@@ -83,9 +83,12 @@ void setup_callbacks(Tox_Dispatch *dispatch)
dispatch, [](Tox *tox, const Tox_Event_Friend_Request *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Request *event, void *user_data) {
Tox_Err_Friend_Add err; Tox_Err_Friend_Add err;
tox_friend_add_norequest(tox, tox_event_friend_request_get_public_key(event), &err); tox_friend_add_norequest(tox, tox_event_friend_request_get_public_key(event), &err);
assert(err == TOX_ERR_FRIEND_ADD_OK || err == TOX_ERR_FRIEND_ADD_OWN_KEY if (!(err == TOX_ERR_FRIEND_ADD_OK || err == TOX_ERR_FRIEND_ADD_OWN_KEY
|| err == TOX_ERR_FRIEND_ADD_ALREADY_SENT || err == TOX_ERR_FRIEND_ADD_ALREADY_SENT
|| err == TOX_ERR_FRIEND_ADD_BAD_CHECKSUM); || err == TOX_ERR_FRIEND_ADD_BAD_CHECKSUM
|| err == TOX_ERR_FRIEND_ADD_MALLOC)) {
printf("unexpected error: %s\n", tox_err_friend_add_to_string(err));
}
}); });
tox_events_callback_friend_status( tox_events_callback_friend_status(
dispatch, [](Tox *tox, const Tox_Event_Friend_Status *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Status *event, void *user_data) {
@@ -120,13 +123,13 @@ void TestBootstrap(Fuzz_Data &input)
[](Tox *tox, Tox_Log_Level level, const char *file, uint32_t line, const char *func, [](Tox *tox, Tox_Log_Level level, const char *file, uint32_t line, const char *func,
const char *message, void *user_data) { const char *message, void *user_data) {
// Log to stdout. // Log to stdout.
if (DEBUG) { if (Fuzz_Data::DEBUG) {
std::printf("[tox1] %c %s:%d(%s): %s\n", tox_log_level_name(level), file, line, std::printf("[tox1] %c %s:%d(%s): %s\n", tox_log_level_name(level), file, line,
func, message); func, message);
} }
}); });
CONSUME1_OR_RETURN(const uint8_t proxy_type, input); CONSUME1_OR_RETURN(const uint8_t, proxy_type, input);
if (proxy_type == 0) { if (proxy_type == 0) {
tox_options_set_proxy_type(opts.get(), TOX_PROXY_TYPE_NONE); tox_options_set_proxy_type(opts.get(), TOX_PROXY_TYPE_NONE);
} else if (proxy_type == 1) { } else if (proxy_type == 1) {
@@ -139,7 +142,7 @@ void TestBootstrap(Fuzz_Data &input)
tox_options_set_proxy_port(opts.get(), 8080); tox_options_set_proxy_port(opts.get(), 8080);
} }
CONSUME1_OR_RETURN(const uint8_t tcp_relay_enabled, input); CONSUME1_OR_RETURN(const uint8_t, tcp_relay_enabled, input);
if (tcp_relay_enabled >= (UINT8_MAX / 2)) { if (tcp_relay_enabled >= (UINT8_MAX / 2)) {
tox_options_set_tcp_port(opts.get(), 33445); tox_options_set_tcp_port(opts.get(), 33445);
} }
@@ -167,7 +170,7 @@ void TestBootstrap(Fuzz_Data &input)
assert(dispatch != nullptr); assert(dispatch != nullptr);
setup_callbacks(dispatch); setup_callbacks(dispatch);
while (input.size > 0) { while (!input.empty()) {
Tox_Err_Events_Iterate error_iterate; Tox_Err_Events_Iterate error_iterate;
Tox_Events *events = tox_events_iterate(tox, true, &error_iterate); Tox_Events *events = tox_events_iterate(tox, true, &error_iterate);
assert(tox_events_equal(null_sys.sys.get(), events, events)); assert(tox_events_equal(null_sys.sys.get(), events, events));

View File

@@ -8,6 +8,7 @@
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include "../../toxcore/crypto_core.h"
#include "../../toxcore/tox.h" #include "../../toxcore/tox.h"
#include "../../toxcore/tox_dispatch.h" #include "../../toxcore/tox_dispatch.h"
#include "../../toxcore/tox_events.h" #include "../../toxcore/tox_events.h"
@@ -109,9 +110,6 @@ void setup_callbacks(Tox_Dispatch *dispatch)
dispatch, [](Tox *tox, const Tox_Event_Friend_Request *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Request *event, void *user_data) {
Tox_Err_Friend_Add err; Tox_Err_Friend_Add err;
tox_friend_add_norequest(tox, tox_event_friend_request_get_public_key(event), &err); tox_friend_add_norequest(tox, tox_event_friend_request_get_public_key(event), &err);
assert(err == TOX_ERR_FRIEND_ADD_OK || err == TOX_ERR_FRIEND_ADD_OWN_KEY
|| err == TOX_ERR_FRIEND_ADD_ALREADY_SENT
|| err == TOX_ERR_FRIEND_ADD_BAD_CHECKSUM);
}); });
tox_events_callback_friend_status( tox_events_callback_friend_status(
dispatch, [](Tox *tox, const Tox_Event_Friend_Status *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Status *event, void *user_data) {
@@ -146,7 +144,7 @@ void TestEndToEnd(Fuzz_Data &input)
[](Tox *tox, Tox_Log_Level level, const char *file, uint32_t line, const char *func, [](Tox *tox, Tox_Log_Level level, const char *file, uint32_t line, const char *func,
const char *message, void *user_data) { const char *message, void *user_data) {
// Log to stdout. // Log to stdout.
if (DEBUG) { if (Fuzz_Data::DEBUG) {
std::printf("[tox1] %c %s:%d(%s): %s\n", tox_log_level_name(level), file, line, std::printf("[tox1] %c %s:%d(%s): %s\n", tox_log_level_name(level), file, line,
func, message); func, message);
} }
@@ -169,7 +167,7 @@ void TestEndToEnd(Fuzz_Data &input)
assert(dispatch != nullptr); assert(dispatch != nullptr);
setup_callbacks(dispatch); setup_callbacks(dispatch);
while (input.size > 0) { while (!input.empty()) {
Tox_Err_Events_Iterate error_iterate; Tox_Err_Events_Iterate error_iterate;
Tox_Events *events = tox_events_iterate(tox, true, &error_iterate); Tox_Events *events = tox_events_iterate(tox, true, &error_iterate);
assert(tox_events_equal(null_sys.sys.get(), events, events)); assert(tox_events_equal(null_sys.sys.get(), events, events));

View File

@@ -20,72 +20,87 @@
#include "../../toxcore/tox_private.h" #include "../../toxcore/tox_private.h"
#include "func_conversion.h" #include "func_conversion.h"
const bool DEBUG = false;
static constexpr tox_mono_time_cb *get_self_clock = ![](Fuzz_System *self) { return self->clock; };
// TODO(iphydf): Put this somewhere shared. // TODO(iphydf): Put this somewhere shared.
struct Network_Addr { struct Network_Addr {
struct sockaddr_storage addr; struct sockaddr_storage addr;
size_t size; size_t size;
}; };
System::System(std::unique_ptr<Tox_System> in_sys, std::unique_ptr<Memory> in_mem,
std::unique_ptr<Network> in_ns, std::unique_ptr<Random> in_rng)
: sys(std::move(in_sys))
, mem(std::move(in_mem))
, ns(std::move(in_ns))
, rng(std::move(in_rng))
{
}
System::System(System &&) = default;
System::~System() { } System::~System() { }
static int recv_common(Fuzz_Data &input, uint8_t *buf, size_t buf_len) static int recv_common(Fuzz_Data &input, uint8_t *buf, size_t buf_len)
{ {
if (input.size < 2) { if (input.size() < 2) {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
const size_t fuzz_len = (input.data[0] << 8) | input.data[1]; CONSUME_OR_ABORT(const uint8_t *fuzz_len_bytes, input, 2);
input.data += 2; const std::size_t fuzz_len = (fuzz_len_bytes[0] << 8) | fuzz_len_bytes[1];
input.size -= 2;
if (fuzz_len == 0xffff) { if (fuzz_len == 0xffff) {
errno = EWOULDBLOCK; errno = EWOULDBLOCK;
if (DEBUG) { if (Fuzz_Data::DEBUG) {
std::printf("recvfrom: no data for tox1\n"); std::printf("recvfrom: no data for tox1\n");
} }
return -1; return -1;
} }
if (DEBUG) { if (Fuzz_Data::DEBUG) {
std::printf( std::printf(
"recvfrom: %zu (%02x, %02x) for tox1\n", fuzz_len, input.data[-2], input.data[-1]); "recvfrom: %zu (%02x, %02x) for tox1\n", fuzz_len, input.data()[-2], input.data()[-1]);
} }
const size_t res = std::min(buf_len, std::min(fuzz_len, input.size)); const size_t res = std::min(buf_len, std::min(fuzz_len, input.size()));
std::copy(input.data, input.data + res, buf); CONSUME_OR_ABORT(const uint8_t *data, input, res);
input.data += res; std::copy(data, data + res, buf);
input.size -= res;
return res; return res;
} }
template <typename F> static void *report_alloc(const char *name, const char *func, std::size_t size, void *ptr)
static void *alloc_common(Fuzz_Data &data, F func)
{ {
CONSUME1_OR_RETURN_VAL(const uint8_t want_alloc, data, func()); if (Fuzz_Data::DEBUG) {
printf("%s: %s(%zu): %s\n", name, func, size, ptr == nullptr ? "false" : "true");
}
return ptr;
}
template <typename F, F Func, typename... Args>
static void *alloc_common(const char *func, std::size_t size, Fuzz_Data &data, Args... args)
{
CONSUME1_OR_RETURN_VAL(
const bool, want_alloc, data, report_alloc("tox1", func, size, Func(args...)));
if (!want_alloc) { if (!want_alloc) {
return nullptr; return nullptr;
} }
return func(); return report_alloc("tox1", func, size, Func(args...));
} }
static constexpr Memory_Funcs fuzz_memory_funcs = { static constexpr Memory_Funcs fuzz_memory_funcs = {
/* .malloc = */ /* .malloc = */
![](Fuzz_System *self, uint32_t size) { ![](Fuzz_System *self, uint32_t size) {
return alloc_common(self->data, [=]() { return std::malloc(size); }); return alloc_common<decltype(std::malloc), std::malloc>("malloc", size, self->data, size);
}, },
/* .calloc = */ /* .calloc = */
![](Fuzz_System *self, uint32_t nmemb, uint32_t size) { ![](Fuzz_System *self, uint32_t nmemb, uint32_t size) {
return alloc_common(self->data, [=]() { return std::calloc(nmemb, size); }); return alloc_common<decltype(std::calloc), std::calloc>(
"calloc", nmemb * size, self->data, nmemb, size);
}, },
/* .realloc = */ /* .realloc = */
![](Fuzz_System *self, void *ptr, uint32_t size) { ![](Fuzz_System *self, void *ptr, uint32_t size) {
return alloc_common(self->data, [=]() { return std::realloc(ptr, size); }); return alloc_common<decltype(std::realloc), std::realloc>(
"realloc", size, self->data, ptr, size);
}, },
/* .free = */ /* .free = */
![](Fuzz_System *self, void *ptr) { std::free(ptr); }, ![](Fuzz_System *self, void *ptr) { std::free(ptr); },
@@ -100,7 +115,7 @@ static constexpr Network_Funcs fuzz_network_funcs = {
![](Fuzz_System *self, int sock) { ![](Fuzz_System *self, int sock) {
assert(sock == 42 || sock == 1337); assert(sock == 42 || sock == 1337);
const size_t count = random_u16(self->rng.get()); const size_t count = random_u16(self->rng.get());
return static_cast<int>(std::min(count, self->data.size)); return static_cast<int>(std::min(count, self->data.size()));
}, },
/* .recv = */ /* .recv = */
![](Fuzz_System *self, int sock, uint8_t *buf, size_t len) { ![](Fuzz_System *self, int sock, uint8_t *buf, size_t len) {
@@ -153,14 +168,17 @@ static constexpr Random_Funcs fuzz_random_funcs = {
/* .random_bytes = */ /* .random_bytes = */
![](Fuzz_System *self, uint8_t *bytes, size_t length) { ![](Fuzz_System *self, uint8_t *bytes, size_t length) {
// Amount of data is limited // Amount of data is limited
const size_t bytes_read = std::min(length, self->data.size); const size_t bytes_read = std::min(length, self->data.size());
// Initialize everything to make MSAN and others happy // Initialize everything to make MSAN and others happy
std::memset(bytes, 0, length); std::memset(bytes, 0, length);
std::copy(self->data.data, self->data.data + bytes_read, bytes); CONSUME_OR_ABORT(const uint8_t *data, self->data, bytes_read);
self->data.data += bytes_read; std::copy(data, data + bytes_read, bytes);
self->data.size -= bytes_read; if (Fuzz_Data::DEBUG) {
if (DEBUG) { if (length == 1) {
std::printf("rng: %02x..%02x[%zu] -> tox1\n", bytes[0], bytes[length - 1], length); std::printf("rng: %d (0x%02x)\n", bytes[0], bytes[0]);
} else {
std::printf("rng: %02x..%02x[%zu]\n", bytes[0], bytes[length - 1], length);
}
} }
}, },
/* .random_uniform = */ /* .random_uniform = */
@@ -184,7 +202,7 @@ Fuzz_System::Fuzz_System(Fuzz_Data &input)
} }
, data(input) , data(input)
{ {
sys->mono_time_callback = get_self_clock; sys->mono_time_callback = [](void *self) { return static_cast<Fuzz_System *>(self)->clock; };
sys->mono_time_user_data = this; sys->mono_time_user_data = this;
sys->mem = mem.get(); sys->mem = mem.get();
sys->ns = ns.get(); sys->ns = ns.get();
@@ -271,7 +289,7 @@ Null_System::Null_System()
std::make_unique<Random>(Random{&null_random_funcs, this}), std::make_unique<Random>(Random{&null_random_funcs, this}),
} }
{ {
sys->mono_time_callback = get_self_clock; sys->mono_time_callback = [](void *self) { return static_cast<Null_System *>(self)->clock; };
sys->mono_time_user_data = this; sys->mono_time_user_data = this;
sys->mem = mem.get(); sys->mem = mem.get();
sys->ns = ns.get(); sys->ns = ns.get();
@@ -288,7 +306,25 @@ static uint16_t get_port(const Network_Addr *addr)
} }
} }
static constexpr Memory_Funcs record_memory_funcs = null_memory_funcs; static constexpr Memory_Funcs record_memory_funcs = {
/* .malloc = */
![](Record_System *self, uint32_t size) {
self->push(true);
return report_alloc(self->name_, "malloc", size, std::malloc(size));
},
/* .calloc = */
![](Record_System *self, uint32_t nmemb, uint32_t size) {
self->push(true);
return report_alloc(self->name_, "calloc", nmemb * size, std::calloc(nmemb, size));
},
/* .realloc = */
![](Record_System *self, void *ptr, uint32_t size) {
self->push(true);
return report_alloc(self->name_, "realloc", size, std::realloc(ptr, size));
},
/* .free = */
![](Record_System *self, void *ptr) { std::free(ptr); },
};
static constexpr Network_Funcs record_network_funcs = { static constexpr Network_Funcs record_network_funcs = {
/* .close = */ ![](Record_System *self, int sock) { return 0; }, /* .close = */ ![](Record_System *self, int sock) { return 0; },
@@ -316,11 +352,10 @@ static constexpr Network_Funcs record_network_funcs = {
![](Record_System *self, int sock, uint8_t *buf, size_t len, Network_Addr *addr) { ![](Record_System *self, int sock, uint8_t *buf, size_t len, Network_Addr *addr) {
assert(sock == 42); assert(sock == 42);
if (self->recvq.empty()) { if (self->recvq.empty()) {
self->recording.push_back(0xff); self->push("\xff\xff");
self->recording.push_back(0xff);
errno = EWOULDBLOCK; errno = EWOULDBLOCK;
if (DEBUG) { if (Fuzz_Data::DEBUG) {
std::printf("recvfrom: no data for %s\n", self->name_); std::printf("%s: recvfrom: no data\n", self->name_);
} }
return -1; return -1;
} }
@@ -340,13 +375,13 @@ static constexpr Network_Funcs record_network_funcs = {
addr->size = sizeof(struct sockaddr); addr->size = sizeof(struct sockaddr);
assert(recvlen > 0 && recvlen <= INT_MAX); assert(recvlen > 0 && recvlen <= INT_MAX);
self->recording.push_back(recvlen >> 8); self->push(uint8_t(recvlen >> 8));
self->recording.push_back(recvlen & 0xff); self->push(uint8_t(recvlen & 0xff));
if (DEBUG) { if (Fuzz_Data::DEBUG) {
std::printf("recvfrom: %zu (%02x, %02x) for %s\n", recvlen, self->recording.end()[-2], std::printf("%s: recvfrom: %zu (%02x, %02x)\n", self->name_, recvlen,
self->recording.end()[-1], self->name_); self->recording().end()[-2], self->recording().end()[-1]);
} }
self->recording.insert(self->recording.end(), buf, buf + recvlen); self->push(buf, recvlen);
return static_cast<int>(recvlen); return static_cast<int>(recvlen);
}, },
/* .send = */ /* .send = */
@@ -380,11 +415,11 @@ static constexpr Random_Funcs record_random_funcs = {
![](Record_System *self, uint8_t *bytes, size_t length) { ![](Record_System *self, uint8_t *bytes, size_t length) {
for (size_t i = 0; i < length; ++i) { for (size_t i = 0; i < length; ++i) {
bytes[i] = simple_rng(self->seed_) & 0xff; bytes[i] = simple_rng(self->seed_) & 0xff;
self->recording.push_back(bytes[i]); self->push(bytes[i]);
} }
if (DEBUG) { if (Fuzz_Data::DEBUG) {
std::printf( std::printf(
"rng: %02x..%02x[%zu] -> %s\n", bytes[0], bytes[length - 1], length, self->name_); "%s: rng: %02x..%02x[%zu]\n", self->name_, bytes[0], bytes[length - 1], length);
} }
}, },
/* .random_uniform = */ /* .random_uniform = */
@@ -402,7 +437,7 @@ Record_System::Record_System(Global &global, uint64_t seed, const char *name)
, seed_(seed) , seed_(seed)
, name_(name) , name_(name)
{ {
sys->mono_time_callback = get_self_clock; sys->mono_time_callback = [](void *self) { return static_cast<Record_System *>(self)->clock; };
sys->mono_time_user_data = this; sys->mono_time_user_data = this;
sys->mem = mem.get(); sys->mem = mem.get();
sys->ns = ns.get(); sys->ns = ns.get();

View File

@@ -6,39 +6,86 @@
#define C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H #define C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H
#include <cstdint> #include <cstdint>
#include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring>
#include <deque> #include <deque>
#include <memory> #include <memory>
#include <vector>
#include <unordered_map> #include <unordered_map>
#include <utility> #include <utility>
#include <vector>
#include "../../toxcore/tox.h" #include "../../toxcore/tox.h"
struct Fuzz_Data { struct Fuzz_Data {
const uint8_t *data; static constexpr bool DEBUG = false;
std::size_t size; static constexpr std::size_t TRACE_TRAP = -1; // 579;
private:
const uint8_t *data_;
const uint8_t *base_;
std::size_t size_;
public:
Fuzz_Data(const uint8_t *input_data, std::size_t input_size) Fuzz_Data(const uint8_t *input_data, std::size_t input_size)
: data(input_data), size(input_size) : data_(input_data)
{} , base_(input_data)
, size_(input_size)
{
}
Fuzz_Data &operator=(const Fuzz_Data &rhs) = delete; Fuzz_Data &operator=(const Fuzz_Data &rhs) = delete;
Fuzz_Data(const Fuzz_Data &rhs) = delete; Fuzz_Data(const Fuzz_Data &rhs) = delete;
uint8_t consume1() struct Consumer {
{ const char *func;
const uint8_t val = data[0]; Fuzz_Data &fd;
++data;
--size;
return val;
}
const uint8_t *consume(std::size_t count) operator bool()
{
// Special case because memcpy causes UB for bool (which can't be
// anything other than 0 or 1).
const bool val = fd.data_[0];
if (DEBUG) {
std::printf("consume@%zu(%s): bool %s\n", fd.pos(), func, val ? "true" : "false");
}
++fd.data_;
--fd.size_;
return val;
}
template <typename T>
operator T()
{
const uint8_t *bytes = fd.consume(func, sizeof(T));
T val;
std::memcpy(&val, bytes, sizeof(T));
return val;
}
};
Consumer consume1(const char *func) { return Consumer{func, *this}; }
std::size_t size() const { return size_; }
std::size_t pos() const { return data_ - base_; }
const uint8_t *data() const { return data_; }
bool empty() const { return size_ == 0; }
const uint8_t *consume(const char *func, std::size_t count)
{ {
const uint8_t *val = data; const uint8_t *val = data_;
data += count; if (DEBUG) {
size -= count; if (pos() == TRACE_TRAP) {
__asm__("int $3");
}
if (count == 1) {
std::printf("consume@%zu(%s): %d (0x%02x)\n", pos(), func, val[0], val[0]);
} else if (count != 0) {
std::printf("consume@%zu(%s): %02x..%02x[%zu]\n", pos(), func, val[0],
val[count - 1], count);
}
}
data_ += count;
size_ -= count;
return val; return val;
} }
}; };
@@ -50,14 +97,14 @@ struct Fuzz_Data {
* *
* @example * @example
* @code * @code
* CONSUME1_OR_RETURN(const uint8_t one_byte, input); * CONSUME1_OR_RETURN(const uint8_t, one_byte, input);
* @endcode * @endcode
*/ */
#define CONSUME1_OR_RETURN(DECL, INPUT) \ #define CONSUME1_OR_RETURN(TYPE, NAME, INPUT) \
if (INPUT.size < 1) { \ if (INPUT.size() < sizeof(TYPE)) { \
return; \ return; \
} \ } \
DECL = INPUT.consume1() TYPE NAME = INPUT.consume1(__func__)
/** @brief Consumes 1 byte of the fuzzer input or returns a value if no data /** @brief Consumes 1 byte of the fuzzer input or returns a value if no data
* available. * available.
@@ -70,11 +117,11 @@ struct Fuzz_Data {
* CONSUME1_OR_RETURN_VAL(const uint8_t one_byte, input, nullptr); * CONSUME1_OR_RETURN_VAL(const uint8_t one_byte, input, nullptr);
* @endcode * @endcode
*/ */
#define CONSUME1_OR_RETURN_VAL(DECL, INPUT, VAL) \ #define CONSUME1_OR_RETURN_VAL(TYPE, NAME, INPUT, VAL) \
if (INPUT.size < 1) { \ if (INPUT.size() < sizeof(TYPE)) { \
return VAL; \ return VAL; \
} \ } \
DECL = INPUT.consume1() TYPE NAME = INPUT.consume1(__func__)
/** @brief Consumes SIZE bytes of the fuzzer input or returns if not enough data available. /** @brief Consumes SIZE bytes of the fuzzer input or returns if not enough data available.
* *
@@ -88,33 +135,55 @@ struct Fuzz_Data {
* @endcode * @endcode
*/ */
#define CONSUME_OR_RETURN(DECL, INPUT, SIZE) \ #define CONSUME_OR_RETURN(DECL, INPUT, SIZE) \
if (INPUT.size < SIZE) { \ if (INPUT.size() < SIZE) { \
return; \ return; \
} \ } \
DECL = INPUT.consume(SIZE) DECL = INPUT.consume(__func__, SIZE)
inline void fuzz_select_target(uint8_t selector, Fuzz_Data &input) #define CONSUME_OR_RETURN_VAL(DECL, INPUT, SIZE, VAL) \
{ if (INPUT.size() < SIZE) { \
// The selector selected no function, so we do nothing and rely on the return VAL; \
// fuzzer to come up with a better selector. } \
} DECL = INPUT.consume(__func__, SIZE)
template <typename Arg, typename... Args> #define CONSUME_OR_ABORT(DECL, INPUT, SIZE) \
void fuzz_select_target(uint8_t selector, Fuzz_Data &input, Arg &&fn, Args &&... args) if (INPUT.size() < SIZE) { \
{ abort(); \
if (selector == sizeof...(Args)) { } \
return fn(input); DECL = INPUT.consume(__func__, SIZE)
using Fuzz_Target = void (*)(Fuzz_Data &input);
template <Fuzz_Target... Args>
struct Fuzz_Target_Selector;
template <Fuzz_Target Arg, Fuzz_Target... Args>
struct Fuzz_Target_Selector<Arg, Args...> {
static void select(uint8_t selector, Fuzz_Data &input)
{
if (selector == sizeof...(Args)) {
return Arg(input);
}
return Fuzz_Target_Selector<Args...>::select(selector, input);
} }
return fuzz_select_target(selector - 1, input, std::forward<Args>(args)...); };
}
template <typename... Args> template <>
void fuzz_select_target(const uint8_t *data, std::size_t size, Args &&... args) struct Fuzz_Target_Selector<> {
static void select(uint8_t selector, Fuzz_Data &input)
{
// The selector selected no function, so we do nothing and rely on the
// fuzzer to come up with a better selector.
}
};
template <Fuzz_Target... Args>
void fuzz_select_target(const uint8_t *data, std::size_t size)
{ {
Fuzz_Data input{data, size}; Fuzz_Data input{data, size};
CONSUME1_OR_RETURN(uint8_t selector, input); CONSUME1_OR_RETURN(const uint8_t, selector, input);
return fuzz_select_target(selector, input, std::forward<Args>(args)...); return Fuzz_Target_Selector<Args...>::select(selector, input);
} }
struct Memory; struct Memory;
@@ -122,14 +191,6 @@ struct Network;
struct Random; struct Random;
struct System { struct System {
std::unique_ptr<Tox_System> sys;
std::unique_ptr<Memory> mem;
std::unique_ptr<Network> ns;
std::unique_ptr<Random> rng;
// Not inline because sizeof of the above 2 structs is not known everywhere.
~System();
/** @brief Deterministic system clock for this instance. /** @brief Deterministic system clock for this instance.
* *
* Different instances can evolve independently. The time is initialised * Different instances can evolve independently. The time is initialised
@@ -137,8 +198,22 @@ struct System {
* friends inside toxcore will be "not timed out" for a long time, messing * friends inside toxcore will be "not timed out" for a long time, messing
* up some logic. Tox moderately depends on the clock being fairly high up * up some logic. Tox moderately depends on the clock being fairly high up
* (not close to 0). * (not close to 0).
*
* We make it a nice large round number so we can recognise it when debugging.
*/ */
uint64_t clock = UINT32_MAX; uint64_t clock = 1000000000;
std::unique_ptr<Tox_System> sys;
std::unique_ptr<Memory> mem;
std::unique_ptr<Network> ns;
std::unique_ptr<Random> rng;
System(std::unique_ptr<Tox_System> sys, std::unique_ptr<Memory> mem,
std::unique_ptr<Network> ns, std::unique_ptr<Random> rng);
System(System &&);
// Not inline because sizeof of the above 2 structs is not known everywhere.
~System();
/** /**
* During bootstrap, move the time forward a decent amount, because friend * During bootstrap, move the time forward a decent amount, because friend
@@ -190,6 +265,8 @@ struct Null_System : System {
* initialised with the same seed will be identical (same keys, etc.). * initialised with the same seed will be identical (same keys, etc.).
*/ */
struct Record_System : System { struct Record_System : System {
static constexpr bool DEBUG = Fuzz_Data::DEBUG;
/** @brief State shared between all tox instances. */ /** @brief State shared between all tox instances. */
struct Global { struct Global {
/** @brief Bound UDP ports and their system instance. /** @brief Bound UDP ports and their system instance.
@@ -211,13 +288,60 @@ struct Record_System : System {
std::deque<std::pair<uint16_t, std::vector<uint8_t>>> recvq; std::deque<std::pair<uint16_t, std::vector<uint8_t>>> recvq;
uint16_t port = 0; //!< Sending port for this system instance. uint16_t port = 0; //!< Sending port for this system instance.
std::vector<uint8_t> recording;
explicit Record_System(Global &global, uint64_t seed, const char *name); Record_System(Global &global, uint64_t seed, const char *name);
Record_System(const Record_System &) = delete;
Record_System operator=(const Record_System &) = delete;
/** @brief Deposit a network packet in this instance's recvq. /** @brief Deposit a network packet in this instance's recvq.
*/ */
void receive(uint16_t send_port, const uint8_t *buf, size_t len); void receive(uint16_t send_port, const uint8_t *buf, size_t len);
void push(bool byte)
{
if (DEBUG) {
if (recording_.size() == Fuzz_Data::TRACE_TRAP) {
__asm__("int $3");
}
std::printf("%s: produce@%zu(bool %s)\n", name_, recording_.size(), byte ? "true" : "false");
}
recording_.push_back(byte);
}
void push(uint8_t byte)
{
if (DEBUG) {
if (recording_.size() == Fuzz_Data::TRACE_TRAP) {
__asm__("int $3");
}
std::printf("%s: produce@%zu(%u (0x%02x))\n", name_, recording_.size(), byte, byte);
}
recording_.push_back(byte);
}
void push(const uint8_t *bytes, std::size_t size)
{
if (DEBUG) {
if (recording_.size() == Fuzz_Data::TRACE_TRAP) {
__asm__("int $3");
}
std::printf("%s: produce@%zu(%02x..%02x[%zu])\n", name_, recording_.size(), bytes[0],
bytes[size - 1], size);
}
recording_.insert(recording_.end(), bytes, bytes + size);
}
template <std::size_t N>
void push(const char (&bytes)[N])
{
push(reinterpret_cast<const uint8_t *>(bytes), N - 1);
}
const std::vector<uint8_t> &recording() const { return recording_; }
std::vector<uint8_t> take_recording() const { return std::move(recording_); }
private:
std::vector<uint8_t> recording_;
}; };
/** @brief Enable debug logging. /** @brief Enable debug logging.

View File

@@ -1,96 +1,17 @@
/* SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2022 The TokTok team. * Copyright © 2022-2024 The TokTok team.
*/ */
#ifndef C_TOXCORE_TESTING_FUZZING_FUZZ_TOX_H #ifndef C_TOXCORE_TESTING_FUZZING_FUZZ_TOX_H
#define C_TOXCORE_TESTING_FUZZING_FUZZ_TOX_H #define C_TOXCORE_TESTING_FUZZING_FUZZ_TOX_H
#include <cassert>
#include <memory> #include <memory>
#include "../../toxcore/DHT.h"
#include "../../toxcore/logger.h"
#include "../../toxcore/network.h" #include "../../toxcore/network.h"
#include "fuzz_support.h"
constexpr uint16_t SIZE_IP_PORT = SIZE_IP6 + sizeof(uint16_t); constexpr uint16_t SIZE_IP_PORT = SIZE_IP6 + sizeof(uint16_t);
template <typename T> template <typename T>
using Ptr = std::unique_ptr<T, void (*)(T *)>; using Ptr = std::unique_ptr<T, void (*)(T *)>;
/** @brief Construct any Tox resource using fuzzer input data.
*
* Constructs (or fails by returning) a valid object of type T and passes it to
* a function specified on the rhs of `>>`. Takes care of cleaning up the
* resource after the specified function returns.
*
* Some `with` instances require additional inputs such as the `Fuzz_Data`
* reference or a logger.
*/
template <typename T>
struct with;
/** @brief Construct a Logger without logging callback.
*/
template <>
struct with<Logger> {
template <typename F>
void operator>>(F &&f)
{
Ptr<Logger> logger(logger_new(), logger_kill);
assert(logger != nullptr);
f(std::move(logger));
}
};
/** @brief Construct an IP_Port by unpacking fuzzer input with `unpack_ip_port`.
*/
template <>
struct with<IP_Port> {
Fuzz_Data &input_;
template <typename F>
void operator>>(F &&f)
{
CONSUME_OR_RETURN(const uint8_t *ipp_packed, input_, SIZE_IP_PORT);
IP_Port ipp;
unpack_ip_port(&ipp, ipp_packed, SIZE_IP6, true);
f(ipp);
}
};
/** @brief Construct a Networking_Core object using the Network vtable passed.
*
* Use `with<Logger>{} >> with<Networking_Core>{input, ns, mem} >> ...` to construct
* a logger and pass it to the Networking_Core constructor function.
*/
template <>
struct with<Networking_Core> {
Fuzz_Data &input_;
const Network *ns_;
const Memory *mem_;
Ptr<Logger> logger_{nullptr, logger_kill};
friend with operator>>(with<Logger> f, with self)
{
f >> [&self](Ptr<Logger> logger) { self.logger_ = std::move(logger); };
return self;
}
template <typename F>
void operator>>(F &&f)
{
with<IP_Port>{input_} >> [&f, this](const IP_Port &ipp) {
Ptr<Networking_Core> net(
new_networking_ex(logger_.get(), mem_, ns_, &ipp.ip, ipp.port, ipp.port + 100, nullptr),
kill_networking);
if (net == nullptr) {
return;
}
f(std::move(net));
};
}
};
#endif // C_TOXCORE_TESTING_FUZZING_FUZZ_TOX_H #endif // C_TOXCORE_TESTING_FUZZING_FUZZ_TOX_H

View File

@@ -17,8 +17,8 @@
* *
* Usage: * Usage:
* *
* bazel build //c-toxcore/testing/fuzzing:protodump_bin && \ * bazel build //c-toxcore/testing/fuzzing:protodump && \
* bazel-bin/c-toxcore/testing/fuzzing/protodump_bin * bazel-bin/c-toxcore/testing/fuzzing/protodump
*/ */
#include <array> #include <array>
#include <cassert> #include <cassert>
@@ -165,15 +165,14 @@ void setup_callbacks(Tox_Dispatch *dispatch)
}); });
} }
void dump(std::vector<uint8_t> &recording, const char *filename) void dump(std::vector<uint8_t> recording, const char *filename)
{ {
std::printf("%zu bytes: %s\n", recording.size(), filename); std::printf("%zu bytes: %s\n", recording.size(), filename);
std::ofstream(filename, std::ios::binary) std::ofstream(filename, std::ios::binary)
.write(reinterpret_cast<const char *>(recording.data()), recording.size()); .write(reinterpret_cast<const char *>(recording.data()), recording.size());
recording.clear();
} }
void RecordBootstrap() void RecordBootstrap(const char *init, const char *bootstrap)
{ {
Record_System::Global global; Record_System::Global global;
@@ -258,13 +257,17 @@ void RecordBootstrap()
sys1.clock += clock_increment; sys1.clock += clock_increment;
sys2.clock += clock_increment; sys2.clock += clock_increment;
sys1.recording.push_back(clock_increment); if (Fuzz_Data::DEBUG) {
sys2.recording.push_back(clock_increment); printf("tox1: rng: %d (for clock)\n", clock_increment);
printf("tox2: rng: %d (for clock)\n", clock_increment);
}
sys1.push(clock_increment);
sys2.push(clock_increment);
}; };
while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE
|| tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE) { || tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE) {
if (DEBUG) { if (Fuzz_Data::DEBUG) {
std::printf("tox1: %d, tox2: %d\n", tox_self_get_connection_status(tox1), std::printf("tox1: %d, tox2: %d\n", tox_self_get_connection_status(tox1),
tox_self_get_connection_status(tox2)); tox_self_get_connection_status(tox2));
} }
@@ -279,7 +282,7 @@ void RecordBootstrap()
while (tox_friend_get_connection_status(tox2, friend_number, nullptr) == TOX_CONNECTION_NONE while (tox_friend_get_connection_status(tox2, friend_number, nullptr) == TOX_CONNECTION_NONE
|| tox_friend_get_connection_status(tox1, 0, nullptr) == TOX_CONNECTION_NONE) { || tox_friend_get_connection_status(tox1, 0, nullptr) == TOX_CONNECTION_NONE) {
if (DEBUG) { if (Fuzz_Data::DEBUG) {
std::printf("tox1: %d, tox2: %d, tox1 -> tox2: %d, tox2 -> tox1: %d\n", std::printf("tox1: %d, tox2: %d, tox1 -> tox2: %d, tox2 -> tox1: %d\n",
tox_self_get_connection_status(tox1), tox_self_get_connection_status(tox2), tox_self_get_connection_status(tox1), tox_self_get_connection_status(tox2),
tox_friend_get_connection_status(tox1, 0, nullptr), tox_friend_get_connection_status(tox1, 0, nullptr),
@@ -290,10 +293,10 @@ void RecordBootstrap()
std::printf("tox clients connected\n"); std::printf("tox clients connected\n");
dump(sys1.recording, "tools/toktok-fuzzer/init/e2e_fuzz_test.dat"); dump(sys1.take_recording(), init);
while (done1 < MESSAGE_COUNT && done2 < MESSAGE_COUNT) { while (done1 < MESSAGE_COUNT && done2 < MESSAGE_COUNT) {
if (DEBUG) { if (Fuzz_Data::DEBUG) {
std::printf("tox1: %d, tox2: %d, tox1 -> tox2: %d, tox2 -> tox1: %d\n", std::printf("tox1: %d, tox2: %d, tox1 -> tox2: %d, tox2 -> tox1: %d\n",
tox_self_get_connection_status(tox1), tox_self_get_connection_status(tox2), tox_self_get_connection_status(tox1), tox_self_get_connection_status(tox2),
tox_friend_get_connection_status(tox1, 0, nullptr), tox_friend_get_connection_status(tox1, 0, nullptr),
@@ -308,9 +311,18 @@ void RecordBootstrap()
tox_kill(tox2); tox_kill(tox2);
tox_kill(tox1); tox_kill(tox1);
dump(sys1.recording, "tools/toktok-fuzzer/corpus/e2e_fuzz_test/bootstrap.dat"); dump(sys1.recording(), bootstrap);
} }
} }
int main(void) { RecordBootstrap(); } int main(int argc, char *argv[])
{
const char *init = "tools/toktok-fuzzer/init/e2e_fuzz_test.dat";
const char *bootstrap = "tools/toktok-fuzzer/corpus/e2e_fuzz_test/bootstrap.dat";
if (argc == 3) {
init = argv[1];
bootstrap = argv[2];
}
RecordBootstrap(init, bootstrap);
}

View File

@@ -1,22 +1,17 @@
#include <cassert> #include <cassert>
#include <cstdio> #include <cstdio>
#include "../../toxcore/crypto_core.h"
#include "../../toxcore/tox.h" #include "../../toxcore/tox.h"
#include "../../toxcore/tox_dispatch.h" #include "../../toxcore/tox_dispatch.h"
#include "../../toxcore/tox_events.h" #include "../../toxcore/tox_events.h"
#include "../../toxcore/tox_private.h"
#include "fuzz_support.h" #include "fuzz_support.h"
#include "fuzz_tox.h" #include "fuzz_tox.h"
namespace { namespace {
/** constexpr bool PROTODUMP_DEBUG = Fuzz_Data::DEBUG;
* Whether to abort the program if a friend connection can be established.
*
* This is useful to make the fuzzer produce minimal startup data so the
* interesting part of the fuzzer (the part that comes after the friend
* connection is established) can run sooner and thus more frequently.
*/
constexpr bool REDUCE_PROTODUMP = false;
void setup_callbacks(Tox_Dispatch *dispatch) void setup_callbacks(Tox_Dispatch *dispatch)
{ {
@@ -30,10 +25,7 @@ void setup_callbacks(Tox_Dispatch *dispatch)
}); });
tox_events_callback_conference_invite( tox_events_callback_conference_invite(
dispatch, [](Tox *tox, const Tox_Event_Conference_Invite *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Conference_Invite *event, void *user_data) {
const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event); assert(event == nullptr);
const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
const uint32_t cookie_length = tox_event_conference_invite_get_cookie_length(event);
tox_conference_join(tox, friend_number, cookie, cookie_length, nullptr);
}); });
tox_events_callback_conference_message( tox_events_callback_conference_message(
dispatch, [](Tox *tox, const Tox_Event_Conference_Message *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Conference_Message *event, void *user_data) {
@@ -57,9 +49,7 @@ void setup_callbacks(Tox_Dispatch *dispatch)
}); });
tox_events_callback_file_recv( tox_events_callback_file_recv(
dispatch, [](Tox *tox, const Tox_Event_File_Recv *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_File_Recv *event, void *user_data) {
const uint32_t friend_number = tox_event_file_recv_get_friend_number(event); assert(event == nullptr);
const uint32_t file_number = tox_event_file_recv_get_file_number(event);
tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, nullptr);
}); });
tox_events_callback_file_recv_chunk( tox_events_callback_file_recv_chunk(
dispatch, [](Tox *tox, const Tox_Event_File_Recv_Chunk *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_File_Recv_Chunk *event, void *user_data) {
@@ -74,58 +64,65 @@ void setup_callbacks(Tox_Dispatch *dispatch)
// OK: friend came online. // OK: friend came online.
const uint32_t friend_number const uint32_t friend_number
= tox_event_friend_connection_status_get_friend_number(event); = tox_event_friend_connection_status_get_friend_number(event);
assert(friend_number != UINT32_MAX); assert(friend_number == 0);
const uint8_t message = 'A';
Tox_Err_Friend_Send_Message err;
tox_friend_send_message(tox, friend_number, TOX_MESSAGE_TYPE_NORMAL, &message, 1, &err);
assert(err == TOX_ERR_FRIEND_SEND_MESSAGE_OK);
}); });
tox_events_callback_friend_lossless_packet( tox_events_callback_friend_lossless_packet(
dispatch, [](Tox *tox, const Tox_Event_Friend_Lossless_Packet *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Lossless_Packet *event, void *user_data) {
const uint32_t friend_number assert(event == nullptr);
= tox_event_friend_lossless_packet_get_friend_number(event);
const uint32_t data_length = tox_event_friend_lossless_packet_get_data_length(event);
const uint8_t *data = tox_event_friend_lossless_packet_get_data(event);
tox_friend_send_lossless_packet(tox, friend_number, data, data_length, nullptr);
}); });
tox_events_callback_friend_lossy_packet( tox_events_callback_friend_lossy_packet(
dispatch, [](Tox *tox, const Tox_Event_Friend_Lossy_Packet *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Lossy_Packet *event, void *user_data) {
const uint32_t friend_number = tox_event_friend_lossy_packet_get_friend_number(event); assert(event == nullptr);
const uint32_t data_length = tox_event_friend_lossy_packet_get_data_length(event);
const uint8_t *data = tox_event_friend_lossy_packet_get_data(event);
tox_friend_send_lossy_packet(tox, friend_number, data, data_length, nullptr);
}); });
tox_events_callback_friend_message( tox_events_callback_friend_message(
dispatch, [](Tox *tox, const Tox_Event_Friend_Message *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Message *event, void *user_data) {
const uint32_t friend_number = tox_event_friend_message_get_friend_number(event); const uint32_t friend_number = tox_event_friend_message_get_friend_number(event);
const Tox_Message_Type type = tox_event_friend_message_get_type(event); assert(friend_number == 0);
const uint32_t message_length = tox_event_friend_message_get_message_length(event); const uint32_t message_length = tox_event_friend_message_get_message_length(event);
assert(message_length == 1);
const uint8_t *message = tox_event_friend_message_get_message(event); const uint8_t *message = tox_event_friend_message_get_message(event);
tox_friend_send_message(tox, friend_number, type, message, message_length, nullptr); const uint8_t reply = message[0] + 1;
Tox_Err_Friend_Send_Message err;
tox_friend_send_message(tox, friend_number, TOX_MESSAGE_TYPE_NORMAL, &reply, 1, &err);
assert(err == TOX_ERR_FRIEND_SEND_MESSAGE_OK);
}); });
tox_events_callback_friend_name( tox_events_callback_friend_name(
dispatch, [](Tox *tox, const Tox_Event_Friend_Name *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Name *event, void *user_data) {
// OK: friend name received. const uint32_t friend_number = tox_event_friend_name_get_friend_number(event);
assert(friend_number == 0);
}); });
tox_events_callback_friend_read_receipt( tox_events_callback_friend_read_receipt(
dispatch, [](Tox *tox, const Tox_Event_Friend_Read_Receipt *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Read_Receipt *event, void *user_data) {
// OK: message has been received. const uint32_t friend_number = tox_event_friend_read_receipt_get_friend_number(event);
assert(friend_number == 0);
const uint32_t message_id = tox_event_friend_read_receipt_get_message_id(event);
uint32_t *done = static_cast<uint32_t *>(user_data);
*done = std::max(*done, message_id);
}); });
tox_events_callback_friend_request( tox_events_callback_friend_request(
dispatch, [](Tox *tox, const Tox_Event_Friend_Request *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Request *event, void *user_data) {
Tox_Err_Friend_Add err; Tox_Err_Friend_Add err;
tox_friend_add_norequest(tox, tox_event_friend_request_get_public_key(event), &err); tox_friend_add_norequest(tox, tox_event_friend_request_get_public_key(event), &err);
assert(err == TOX_ERR_FRIEND_ADD_OK || err == TOX_ERR_FRIEND_ADD_OWN_KEY
|| err == TOX_ERR_FRIEND_ADD_ALREADY_SENT
|| err == TOX_ERR_FRIEND_ADD_BAD_CHECKSUM);
}); });
tox_events_callback_friend_status( tox_events_callback_friend_status(
dispatch, [](Tox *tox, const Tox_Event_Friend_Status *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Status *event, void *user_data) {
// OK: friend status received. const uint32_t friend_number = tox_event_friend_status_get_friend_number(event);
assert(friend_number == 0);
}); });
tox_events_callback_friend_status_message( tox_events_callback_friend_status_message(
dispatch, [](Tox *tox, const Tox_Event_Friend_Status_Message *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Status_Message *event, void *user_data) {
// OK: friend status message received. const uint32_t friend_number = tox_event_friend_status_message_get_friend_number(event);
assert(friend_number == 0);
}); });
tox_events_callback_friend_typing( tox_events_callback_friend_typing(
dispatch, [](Tox *tox, const Tox_Event_Friend_Typing *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Friend_Typing *event, void *user_data) {
// OK: friend may be typing. const uint32_t friend_number = tox_event_friend_typing_get_friend_number(event);
assert(friend_number == 0);
assert(!tox_event_friend_typing_get_typing(event));
}); });
tox_events_callback_self_connection_status( tox_events_callback_self_connection_status(
dispatch, [](Tox *tox, const Tox_Event_Self_Connection_Status *event, void *user_data) { dispatch, [](Tox *tox, const Tox_Event_Self_Connection_Status *event, void *user_data) {
@@ -135,6 +132,15 @@ void setup_callbacks(Tox_Dispatch *dispatch)
void TestEndToEnd(Fuzz_Data &input) void TestEndToEnd(Fuzz_Data &input)
{ {
/**
* Whether to abort the program if a friend connection can be established.
*
* This is useful to make the fuzzer produce minimal startup data so the
* interesting part of the fuzzer (the part that comes after the friend
* connection is established) can run sooner and thus more frequently.
*/
const bool PROTODUMP_REDUCE = getenv("PROTODUMP_REDUCE") != nullptr;
Fuzz_System sys(input); Fuzz_System sys(input);
Ptr<Tox_Options> opts(tox_options_new(nullptr), tox_options_free); Ptr<Tox_Options> opts(tox_options_new(nullptr), tox_options_free);
@@ -146,7 +152,7 @@ void TestEndToEnd(Fuzz_Data &input)
[](Tox *tox, Tox_Log_Level level, const char *file, uint32_t line, const char *func, [](Tox *tox, Tox_Log_Level level, const char *file, uint32_t line, const char *func,
const char *message, void *user_data) { const char *message, void *user_data) {
// Log to stdout. // Log to stdout.
if (DEBUG) { if (PROTODUMP_DEBUG) {
std::printf("[tox1] %c %s:%d(%s): %s\n", tox_log_level_name(level), file, line, std::printf("[tox1] %c %s:%d(%s): %s\n", tox_log_level_name(level), file, line,
func, message); func, message);
} }
@@ -169,20 +175,26 @@ void TestEndToEnd(Fuzz_Data &input)
assert(dispatch != nullptr); assert(dispatch != nullptr);
setup_callbacks(dispatch); setup_callbacks(dispatch);
while (input.size > 0) { while (!input.empty()) {
Tox_Err_Events_Iterate error_iterate; Tox_Err_Events_Iterate error_iterate;
Tox_Events *events = tox_events_iterate(tox, true, &error_iterate); Tox_Events *events = tox_events_iterate(tox, true, &error_iterate);
assert(tox_events_equal(tox_get_system(tox), events, events)); tox_events_equal(tox_get_system(tox), events, events); // TODO(iphydf): assert?
tox_dispatch_invoke(dispatch, events, tox, nullptr); tox_dispatch_invoke(dispatch, events, tox, nullptr);
tox_events_free(events); tox_events_free(events);
sys.clock += std::max(System::MIN_ITERATION_INTERVAL, random_u08(sys.rng.get())); const uint8_t clock_increment = random_u08(sys.rng.get());
if (PROTODUMP_DEBUG) {
printf("clock increment: %d\n", clock_increment);
}
sys.clock += std::max(System::MIN_ITERATION_INTERVAL, clock_increment);
} }
if (REDUCE_PROTODUMP) { if (PROTODUMP_REDUCE) {
assert(tox_friend_get_connection_status(tox, 0, nullptr) != 2); assert(tox_friend_get_connection_status(tox, 0, nullptr) != 2);
} else { } else {
printf("friend: %d\n", tox_friend_get_connection_status(tox, 0, nullptr)); printf("friend: %d\n", tox_friend_get_connection_status(tox, 0, nullptr));
printf("self: %d\n", tox_self_get_connection_status(tox)); printf("self: %d\n", tox_self_get_connection_status(tox));
assert(tox_friend_get_connection_status(tox, 0, nullptr) == 2);
assert(input.empty());
} }
tox_dispatch_free(dispatch); tox_dispatch_free(dispatch);

View File

@@ -0,0 +1,14 @@
#!/bin/sh
set -eux
bazel test --config=asan-libfuzzer //c-toxcore/testing/fuzzing:protodump_reduce_test
bazel build --config=asan-libfuzzer //c-toxcore/testing/fuzzing:protodump
bazel-bin/c-toxcore/testing/fuzzing/protodump | grep -v '^tox2'
bazel build --config=asan-libfuzzer //c-toxcore/testing/fuzzing:protodump_reduce_bin
bazel-bin/c-toxcore/testing/fuzzing/protodump_reduce_bin "$PWD/tools/toktok-fuzzer/init/e2e_fuzz_test.dat"
#export PROTODUMP_REDUCE=1
#bazel-bin/c-toxcore/testing/fuzzing/protodump_reduce_bin -minimize_crash=1 "$PWD/tools/toktok-fuzzer/init/e2e_fuzz_test.dat"

View File

@@ -17,7 +17,7 @@ void TestSaveDataLoading(Fuzz_Data &input)
assert(tox_options != nullptr); assert(tox_options != nullptr);
assert(error_options == TOX_ERR_OPTIONS_NEW_OK); assert(error_options == TOX_ERR_OPTIONS_NEW_OK);
const size_t savedata_size = input.size; const size_t savedata_size = input.size();
CONSUME_OR_RETURN(const uint8_t *savedata, input, savedata_size); CONSUME_OR_RETURN(const uint8_t *savedata, input, savedata_size);
Null_System sys; Null_System sys;

View File

@@ -5,7 +5,7 @@ COMMON_CMAKE_OPTIONS="-DCMAKE_C_COMPILER=afl-clang-lto -DCMAKE_CXX_COMPILER=afl-
# move to repo root # move to repo root
cd ../ cd ../
# build fuzzer target UBSAN # build fuzz_test target UBSAN
mkdir -p _afl_build_ubsan mkdir -p _afl_build_ubsan
cd _afl_build_ubsan cd _afl_build_ubsan
@@ -14,14 +14,14 @@ export AFL_USE_UBSAN=1
# build c-toxcore using afl instrumentation # build c-toxcore using afl instrumentation
cmake -DCMAKE_BUILD_TYPE=Debug "$COMMON_CMAKE_OPTIONS" .. cmake -DCMAKE_BUILD_TYPE=Debug "$COMMON_CMAKE_OPTIONS" ..
# build fuzzer target # build fuzz_test target
cmake --build ./ --target bootstrap_fuzzer cmake --build ./ --target bootstrap_fuzz_test
unset AFL_USE_UBSAN unset AFL_USE_UBSAN
cd .. cd ..
# build fuzzer target MSAN # build fuzz_test target MSAN
mkdir -p _afl_build_msan mkdir -p _afl_build_msan
cd _afl_build_msan cd _afl_build_msan
@@ -30,14 +30,14 @@ export AFL_USE_MSAN=1
# build c-toxcore using afl instrumentation # build c-toxcore using afl instrumentation
cmake -DCMAKE_BUILD_TYPE=Debug "$COMMON_CMAKE_OPTIONS" .. cmake -DCMAKE_BUILD_TYPE=Debug "$COMMON_CMAKE_OPTIONS" ..
# build fuzzer target # build fuzz_test target
cmake --build ./ --target bootstrap_fuzzer cmake --build ./ --target bootstrap_fuzz_test
unset AFL_USE_MSAN unset AFL_USE_MSAN
cd .. cd ..
# build fuzzer target ASAN # build fuzz_test target ASAN
mkdir -p _afl_build_asan mkdir -p _afl_build_asan
cd _afl_build_asan cd _afl_build_asan
@@ -46,26 +46,26 @@ export AFL_USE_ASAN=1
# build c-toxcore using afl instrumentation # build c-toxcore using afl instrumentation
cmake -DCMAKE_BUILD_TYPE=Debug "$COMMON_CMAKE_OPTIONS" .. cmake -DCMAKE_BUILD_TYPE=Debug "$COMMON_CMAKE_OPTIONS" ..
# build fuzzer target # build fuzz_test target
cmake --build ./ --target bootstrap_fuzzer cmake --build ./ --target bootstrap_fuzz_test
unset AFL_USE_ASAN unset AFL_USE_ASAN
cd .. cd ..
# build fuzzer target without sanitizers for afl-tmin # build fuzz_test target without sanitizers for afl-tmin
mkdir -p _afl_build mkdir -p _afl_build
cd _afl_build cd _afl_build
# build c-toxcore using afl instrumentation # build c-toxcore using afl instrumentation
cmake -DCMAKE_BUILD_TYPE=Debug "$COMMON_CMAKE_OPTIONS" .. cmake -DCMAKE_BUILD_TYPE=Debug "$COMMON_CMAKE_OPTIONS" ..
# build fuzzer target # build fuzz_test target
cmake --build ./ --target bootstrap_fuzzer cmake --build ./ --target bootstrap_fuzz_test
cd .. cd ..
# build fuzzer target with CmpLog # build fuzz_test target with CmpLog
mkdir -p _afl_build_cmplog mkdir -p _afl_build_cmplog
cd _afl_build_cmplog cd _afl_build_cmplog
@@ -74,27 +74,27 @@ export AFL_LLVM_CMPLOG=1
# build c-toxcore using afl instrumentation # build c-toxcore using afl instrumentation
cmake -DCMAKE_BUILD_TYPE=Debug "$COMMON_CMAKE_OPTIONS" .. cmake -DCMAKE_BUILD_TYPE=Debug "$COMMON_CMAKE_OPTIONS" ..
# build fuzzer target # build fuzz_test target
cmake --build ./ --target bootstrap_fuzzer cmake --build ./ --target bootstrap_fuzz_test
unset AFL_LLVM_CMPLOG unset AFL_LLVM_CMPLOG
cd .. cd ..
# build fuzzer target for code coverage # build fuzz_test target for code coverage
mkdir -p _cov_build mkdir -p _cov_build
cd _cov_build cd _cov_build
# build c-toxcore using afl instrumentation # build c-toxcore using afl instrumentation
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fprofile-arcs -ftest-coverage" -DCMAKE_C_FLAGS="-fprofile-arcs -ftest-coverage" -DCMAKE_VERBOSE_MAKEFILE=ON "$COMMON_CMAKE_OPTIONS" .. cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fprofile-arcs -ftest-coverage" -DCMAKE_C_FLAGS="-fprofile-arcs -ftest-coverage" -DCMAKE_VERBOSE_MAKEFILE=ON "$COMMON_CMAKE_OPTIONS" ..
# build fuzzer target # build fuzz_test target
cmake --build ./ --target bootstrap_fuzzer cmake --build ./ --target bootstrap_fuzz_test
# back to repo root # back to repo root
cd ../ cd ../
# Create fuzzer working directory # Create fuzz_test working directory
mkdir -p _afl_out mkdir -p _afl_out
@@ -106,21 +106,21 @@ export AFL_AUTORESUME=1
# faster startup # faster startup
export AFL_FAST_CAL=1 export AFL_FAST_CAL=1
echo "connect to the fuzzers using: screen -x fuzz" echo "connect to the fuzz_tests using: screen -x fuzz"
echo "if fuzzing doesn't start execute the following as root:" echo "if fuzzing doesn't start execute the following as root:"
echo "" echo ""
echo "echo core >/proc/sys/kernel/core_pattern" echo "echo core >/proc/sys/kernel/core_pattern"
echo "echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor" echo "echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor"
# Main fuzzer, keeps complete corpus # Main fuzz_test, keeps complete corpus
screen -dmS fuzz afl-fuzz -M fuzz0 "$AFL_ARGS" -c ./_afl_build_cmplog/bootstrap_fuzzer ./_afl_build/bootstrap_fuzzer screen -dmS fuzz afl-fuzz -M fuzz0 "$AFL_ARGS" -c ./_afl_build_cmplog/bootstrap_fuzz_test ./_afl_build/bootstrap_fuzz_test
sleep 10s sleep 10s
# Secondary fuzzers # Secondary fuzz_tests
screen -S fuzz -X screen afl-fuzz -S fuzz1 "$AFL_ARGS" -- ./_afl_build_msan/bootstrap_fuzzer screen -S fuzz -X screen afl-fuzz -S fuzz1 "$AFL_ARGS" -- ./_afl_build_msan/bootstrap_fuzz_test
sleep 1s sleep 1s
screen -S fuzz -X screen afl-fuzz -S fuzz2 "$AFL_ARGS" ./_afl_build_ubsan/bootstrap_fuzzer screen -S fuzz -X screen afl-fuzz -S fuzz2 "$AFL_ARGS" ./_afl_build_ubsan/bootstrap_fuzz_test
sleep 1s sleep 1s
screen -S fuzz -X screen afl-fuzz -S fuzz3 "$AFL_ARGS" ./_afl_build_asan/bootstrap_fuzzer screen -S fuzz -X screen afl-fuzz -S fuzz3 "$AFL_ARGS" ./_afl_build_asan/bootstrap_fuzz_test

View File

@@ -196,13 +196,13 @@ void ac_iterate(ACSession *ac)
int ac_queue_message(Mono_Time *mono_time, void *acp, struct RTPMessage *msg) int ac_queue_message(Mono_Time *mono_time, void *acp, struct RTPMessage *msg)
{ {
if (acp == nullptr || msg == nullptr) { ACSession *ac = (ACSession *)acp;
if (ac == nullptr || msg == nullptr) {
free(msg); free(msg);
return -1; return -1;
} }
ACSession *ac = (ACSession *)acp;
if ((msg->header.pt & 0x7f) == (RTP_TYPE_AUDIO + 2) % 128) { if ((msg->header.pt & 0x7f) == (RTP_TYPE_AUDIO + 2) % 128) {
LOGGER_WARNING(ac->log, "Got dummy!"); LOGGER_WARNING(ac->log, "Got dummy!");
free(msg); free(msg);

View File

@@ -208,6 +208,8 @@ static int bwc_send_custom_lossy_packet(Tox *tox, int32_t friendnumber, const ui
static int bwc_handle_data(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object) static int bwc_handle_data(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object)
{ {
BWController *bwc = (BWController *)object;
if (length - 1 != sizeof(struct BWCMessage)) { if (length - 1 != sizeof(struct BWCMessage)) {
return -1; return -1;
} }
@@ -218,5 +220,5 @@ static int bwc_handle_data(Messenger *m, uint32_t friendnumber, const uint8_t *d
offset += net_unpack_u32(data + offset, &msg.recv); offset += net_unpack_u32(data + offset, &msg.recv);
assert(offset == length); assert(offset == length);
return on_update((BWController *)object, &msg); return on_update(bwc, &msg);
} }

View File

@@ -290,8 +290,9 @@ static void group_av_peer_delete(void *object, uint32_t groupnumber, void *peer_
static void group_av_groupchat_delete(void *object, uint32_t groupnumber) static void group_av_groupchat_delete(void *object, uint32_t groupnumber)
{ {
if (object != nullptr) { Group_AV *group_av = (Group_AV *)object;
kill_group_av((Group_AV *)object); if (group_av != nullptr) {
kill_group_av(group_av);
} }
} }
@@ -404,12 +405,13 @@ static int decode_audio_packet(Group_AV *group_av, Group_Peer_AV *peer_av, uint3
static int handle_group_audio_packet(void *object, uint32_t groupnumber, uint32_t friendgroupnumber, void *peer_object, static int handle_group_audio_packet(void *object, uint32_t groupnumber, uint32_t friendgroupnumber, void *peer_object,
const uint8_t *packet, uint16_t length) const uint8_t *packet, uint16_t length)
{ {
if (peer_object == nullptr || object == nullptr || length <= sizeof(uint16_t)) { Group_AV *group_av = (Group_AV *)object;
Group_Peer_AV *peer_av = (Group_Peer_AV *)peer_object;
if (group_av == nullptr || peer_av == nullptr || length <= sizeof(uint16_t)) {
return -1; return -1;
} }
Group_Peer_AV *peer_av = (Group_Peer_AV *)peer_object;
Group_Audio_Packet *pk = (Group_Audio_Packet *)calloc(1, sizeof(Group_Audio_Packet)); Group_Audio_Packet *pk = (Group_Audio_Packet *)calloc(1, sizeof(Group_Audio_Packet));
if (pk == nullptr) { if (pk == nullptr) {
@@ -433,7 +435,7 @@ static int handle_group_audio_packet(void *object, uint32_t groupnumber, uint32_
return -1; return -1;
} }
while (decode_audio_packet((Group_AV *)object, peer_av, groupnumber, friendgroupnumber) == 0) { while (decode_audio_packet(group_av, peer_av, groupnumber, friendgroupnumber) == 0) {
/* Continue. */ /* Continue. */
} }

View File

@@ -60,7 +60,7 @@ typedef struct MSIMessage {
static void msg_init(MSIMessage *dest, MSIRequest request); static void msg_init(MSIMessage *dest, MSIRequest request);
static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data, uint16_t length); static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data, uint16_t length);
static uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const void *value, uint8_t value_len, static uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const uint8_t *value, uint8_t value_len,
uint16_t *length); uint16_t *length);
static int send_message(const Messenger *m, uint32_t friend_number, const MSIMessage *msg); static int send_message(const Messenger *m, uint32_t friend_number, const MSIMessage *msg);
static int send_error(const Messenger *m, uint32_t friend_number, MSIError error); static int send_error(const Messenger *m, uint32_t friend_number, MSIError error);
@@ -425,7 +425,7 @@ static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data
return 0; return 0;
} }
static uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const void *value, uint8_t value_len, static uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const uint8_t *value, uint8_t value_len,
uint16_t *length) uint16_t *length)
{ {
/* Parse a single header for sending */ /* Parse a single header for sending */
@@ -587,7 +587,7 @@ static MSICall *new_call(MSISession *session, uint32_t friend_number)
session->calls_tail = friend_number; session->calls_tail = friend_number;
session->calls_head = friend_number; session->calls_head = friend_number;
} else if (session->calls_tail < friend_number) { /* Appending */ } else if (session->calls_tail < friend_number) { /* Appending */
MSICall **tmp = (MSICall **)realloc(session->calls, sizeof(MSICall *) * (friend_number + 1)); MSICall **tmp = (MSICall **)realloc(session->calls, (friend_number + 1) * sizeof(MSICall *));
if (tmp == nullptr) { if (tmp == nullptr) {
free(rc); free(rc);
@@ -657,12 +657,13 @@ CLEAR_CONTAINER:
} }
static void on_peer_status(Messenger *m, uint32_t friend_number, uint8_t status, void *data) static void on_peer_status(Messenger *m, uint32_t friend_number, uint8_t status, void *data)
{ {
MSISession *session = (MSISession *)data;
if (status != 0) { if (status != 0) {
// Friend is online. // Friend is online.
return; return;
} }
MSISession *session = (MSISession *)data;
LOGGER_DEBUG(m->log, "Friend %d is now offline", friend_number); LOGGER_DEBUG(m->log, "Friend %d is now offline", friend_number);
pthread_mutex_lock(session->mutex); pthread_mutex_lock(session->mutex);
@@ -851,9 +852,10 @@ static void handle_pop(MSICall *call, const MSIMessage *msg)
} }
static void handle_msi_packet(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length, void *object) static void handle_msi_packet(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length, void *object)
{ {
MSISession *session = (MSISession *)object;
LOGGER_DEBUG(m->log, "Got msi message"); LOGGER_DEBUG(m->log, "Got msi message");
MSISession *session = (MSISession *)object;
MSIMessage msg; MSIMessage msg;
if (msg_parse_in(m->log, &msg, data, length) == -1) { if (msg_parse_in(m->log, &msg, data, length) == -1) {

View File

@@ -106,8 +106,9 @@ uint16_t rb_size(const RingBuffer *b)
uint16_t rb_data(const RingBuffer *b, void **dest) uint16_t rb_data(const RingBuffer *b, void **dest)
{ {
uint16_t i; uint16_t i;
const uint16_t size = rb_size(b);
for (i = 0; i < rb_size(b); ++i) { for (i = 0; i < size; ++i) {
dest[i] = b->data[(b->start + i) % b->size]; dest[i] = b->data[(b->start + i) % b->size];
} }

Some files were not shown because too many files have changed in this diff Show More