diff --git a/.devcontainer/raspi/Dockerfile b/.devcontainer/raspi/Dockerfile index e462e3f5..dca356ad 100644 --- a/.devcontainer/raspi/Dockerfile +++ b/.devcontainer/raspi/Dockerfile @@ -58,7 +58,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && apt-get clean -y\ && update-alternatives --install /usr/bin/python python /usr/bin/python3 50 -RUN echo "deb https://apt.llvm.org/jammy/ llvm-toolchain-jammy-${LLVM_VERSION} main" > /etc/apt/sources.list.d/apt.llvm.org.list && \ +RUN echo "deb https://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-${LLVM_VERSION} main" > /etc/apt/sources.list.d/apt.llvm.org.list && \ curl -sL https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \ apt-get update && apt-get install -y --no-install-recommends \ clang-format-${LLVM_VERSION} \ diff --git a/.devcontainer/ubuntu/Dockerfile b/.devcontainer/ubuntu/Dockerfile index 6eef9917..bb6bfb31 100644 --- a/.devcontainer/ubuntu/Dockerfile +++ b/.devcontainer/ubuntu/Dockerfile @@ -62,7 +62,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # Remove this once stdeb is fully released for ubuntu:24.04 (python3.12) RUN pip3 install git+https://github.com/astraw/stdeb.git --break-system-packages -RUN echo "deb https://apt.llvm.org/jammy/ llvm-toolchain-jammy-${LLVM_VERSION} main" > /etc/apt/sources.list.d/apt.llvm.org.list && \ +RUN echo "deb https://apt.llvm.org/noble/ llvm-toolchain-noble-${LLVM_VERSION} main" > /etc/apt/sources.list.d/apt.llvm.org.list && \ curl -sL https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \ apt-get update && apt-get install -y --no-install-recommends \ clang-format-${LLVM_VERSION} \ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..7f15cf68 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +# The sole reason of this file is to make github assign reviews to +# all team members explicitly. +# Every member in https://github.com/orgs/midokura/teams/device/members +# is responsible for review of any PRs in this repo. +# The each members are intentionally listed here instead of @midokura/device +# team because we want to assign reviews to individuals, not the team. +# +# https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-code-owners + +* @midokura/device + +# We need to ensure documentation is validated at PR time. +# The validation must be done before merging to ensure we can do a release and +# generate the documentation artifacts safely +*.md @jimken-mido @midokura/device +*.rst @jimken-mido @midokura/device diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..e82cfece --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,16 @@ + + + + + +## What? + +Include an explanation of what are the changes about. + +## Why? + +Include an explanation of why we need the changes. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..47dfc855 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,189 @@ +# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +on: + workflow_call: + inputs: + builder-tag: + description: The builder tag to be used + default: latest + required: false + type: string + package-namespace: + description: The package namespace for docker images + default: ${{ github.repository }} + required: false + type: string + ref: + type: string + required: true + +jobs: + build-agent: + name: Agent (${{ matrix.name }}, ${{ matrix.platform }}) + runs-on: ${{ matrix.runner }} + container: + image: ghcr.io/${{ inputs.package-namespace }}/builder-${{ matrix.name }}:${{ inputs.builder-tag }} + credentials: + username: ${{ github.actor }} + password: ${{ github.token }} + options: ${{ startsWith(matrix.runner, 'buildjet') && '--user 1000:1001' || '--user 1001:127' }} + timeout-minutes: 8 # the worst case is 3 minutes + strategy: + fail-fast: false + matrix: + include: + - name: raspios-bookworm + runner: ${{ github.event.repository.private && 'buildjet-4vcpu-ubuntu-2204-arm' || 'ubuntu-24.04-arm' }} + platform: arm64 + - name: ubuntu-noble + runner: ${{ github.event.repository.private && 'buildjet-4vcpu-ubuntu-2204-arm' || 'ubuntu-24.04-arm' }} + platform: arm64 + - name: ubuntu-noble + runner: ${{ github.event.repository.private && 'buildjet-4vcpu-ubuntu-2204' || 'ubuntu-24.04' }} + platform: amd64 + steps: + - name: Checkout source + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} + + - name: Build + run: bear -- make -j$((`nproc` * 2)) CFLAGS="-g -Werror" + + - name: Generate SBOM + run: | + ./scripts/sources bin/evp_agent > sources.lst + ./scripts/mk-sbom -d -c `dpkg -l libc6 | awk '/libc6/ {print $3}'` sources.lst + + - name: Agent Debian Package + run: make dist + + - name: Upload agent debian package + uses: actions/upload-artifact@v4 + with: + name: agent-deb-${{ matrix.name }}-${{ matrix.platform }}-${{ github.run_id }} + path: evp-agent*.deb + + - name: Upload sdk debian package + uses: actions/upload-artifact@v4 + with: + name: libevp-app-sdk-dev-${{ matrix.name }}-${{ matrix.platform }}-${{ github.run_id }} + path: libevp-app-sdk-dev*.deb + + - name: Upload SBOM + uses: actions/upload-artifact@v4 + with: + name: sbom-agent-${{ matrix.name }}-${{ matrix.platform }}-${{ github.run_id }} + path: | + compile_commands.json + sources.lst + sbom.tsv + sbom-files.txt + sbom-tmp.txt + + build-sdk: + name: SDK (${{ matrix.name }}, ${{ matrix.platform }}) + runs-on: ${{ matrix.runner }} + container: + image: ghcr.io/${{ inputs.package-namespace }}/builder-${{ matrix.name }}:${{ inputs.builder-tag }} + credentials: + username: ${{ github.actor }} + password: ${{ github.token }} + options: ${{ startsWith(matrix.runner, 'buildjet') && '--user 1000:1001' || '--user 1001:127' }} + timeout-minutes: 8 # the worst case is 3 minutes + strategy: + fail-fast: false + matrix: + include: + - name: raspios-bookworm + runner: ${{ github.event.repository.private && 'buildjet-4vcpu-ubuntu-2204-arm' || 'ubuntu-24.04-arm' }} + platform: arm64 + - name: ubuntu-noble + runner: ${{ github.event.repository.private && 'buildjet-4vcpu-ubuntu-2204-arm' || 'ubuntu-24.04-arm' }} + platform: arm64 + - name: ubuntu-noble + runner: ${{ github.event.repository.private && 'buildjet-4vcpu-ubuntu-2204' || 'ubuntu-24.04' }} + platform: amd64 + + steps: + - name: Checkout source + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} + + - name: Build SDK + run: make -j$((`nproc` * 2)) sdk \ + CFLAGS="-O2 -Werror" \ + KBUILD_DEFCONFIG=configs/linux-docker.config + + - name: Install python test dependencies + working-directory: src/python-evp-app-sdk + run: | + python3 -m venv .venv + . .venv/bin/activate + pip install \ + -e . \ + -r requirements.test.txt + + - name: Run python SDK tests + working-directory: src/python-evp-app-sdk + run: | + . .venv/bin/activate + python -m pytest \ + --cov=evp.app \ + --cov-report="xml:pysdk-cov.xml" \ + --junit-xml="pysdk-test-res.xml" \ + -v + + - name: Publish pytest coverage + id: pysdk-cov + uses: MishaKav/pytest-coverage-comment@main + if: always() + with: + title: EVP Python Application SDK coverage report + badge-title: Python Application SDK + coverage-path-prefix: src/python-evp-app-sdk/evp/app/ + pytest-xml-coverage-path: src/python-evp-app-sdk/pysdk-cov.xml + junitxml-path: src/python-evp-app-sdk/pysdk-test-res.xml + junitxml-title: Python Application SDK test report + + - name: Publish pytest results to summary + if: steps.pysdk-cov.outputs.summaryReport + run: echo ${{ steps.pysdk-cov.outputs.summaryReport }} >> $GITHUB_STEP_SUMMARY + + - name: Build Python package + working-directory: src/python-evp-app-sdk + run: python3 -m build + + - name: SDK Debian package + working-directory: src/python-evp-app-sdk + run: python setup.py --command-packages=stdeb.command bdist_deb + + - uses: actions/upload-artifact@v4 + with: + name: python-sdk-${{ matrix.name }}-${{ matrix.platform }}-${{ github.run_id }} + path: src/python-evp-app-sdk/dist/* + + - uses: actions/upload-artifact@v4 + with: + name: python-sdk-deb-${{ matrix.name }}-${{ matrix.platform }}-${{ github.run_id }} + path: src/python-evp-app-sdk/deb_dist/*.deb + + run-static-analysis: + name: Static Code Analysis + runs-on: ubuntu-24.04 + container: + image: ghcr.io/${{ inputs.package-namespace }}/builder-ubuntu-noble:${{ inputs.builder-tag }} + options: --user 1001:127 + timeout-minutes: 8 # the worst case is 3 minutes + + steps: + - name: Checkout source + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} + + - name: Run cppcheck analysis + run: make -j$((`nproc` * 2)) CFLAGS="-Werror" TOOL=cppcheck analysis diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml new file mode 100644 index 00000000..3280f08f --- /dev/null +++ b/.github/workflows/builder.yml @@ -0,0 +1,163 @@ +# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +name: Build and push builders (if necessary) + +on: + workflow_dispatch: + inputs: + ref: + description: The ref sha to checkout evp-agent + type: string + required: false + default: main + package-namespace: + description: The package namespace for docker images + required: true + type: string + workflow_call: + inputs: + ref: + type: string + required: false + package-namespace: + description: The package namespace for docker images + default: ${{ github.repository }} + required: false + type: string + outputs: + builder-tag: + description: tag + value: ${{ jobs.builder-necessary.outputs.builder-tag }} + +concurrency: + group: ${{ github.workflow }} @ build-builders-${{ github.ref }} + cancel-in-progress: true + +jobs: + builder-necessary: + name: Is builder necessary? + runs-on: ubuntu-24.04 + outputs: + build: ${{ steps.changed-files.outputs.all_changed_and_modified_files != '' }} + builder-tag: ${{ steps.builder-tag.outputs.tag }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.ref }} + + - uses: tj-actions/changed-files@v41 + id: changed-files + with: + files: | + .devcontainer/ubuntu/Dockerfile + .devcontainer/raspi/Dockerfile + .github/workflows/builder.yml + + - name: Set builder tag + id: builder-tag + run: | + echo "Modified: ${{ steps.changed-files.outputs.all_changed_and_modified_files != '' }}" + tag=${{ steps.changed-files.outputs.all_changed_and_modified_files != '' && github.ref != 'refs/heads/main' && github.sha || 'latest' }} + echo "github.ref is: ${{ github.ref }}" + echo "Is not main branch? ${{ github.ref != 'refs/heads/main' }}" + echo "github.sha is: ${{ github.sha }}" + echo "Tag: $tag" + echo "tag=$tag" >> $GITHUB_OUTPUT + echo Modified file list: + for file in ${{ steps.changed-files.outputs.all_changed_and_modified_files }}; do + echo "$file" + done + + build-push-raspi: + name: Build and push raspios bookworm builder + if: ${{ needs.builder-necessary.outputs.build == 'true' }} + needs: + - builder-necessary + runs-on: ${{ github.event.repository.private && 'buildjet-8vcpu-ubuntu-2204-arm' || 'ubuntu-24.04-arm' }} + + steps: + - name: Checkout the code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Github Registry + uses: docker/login-action@v3 + with: + username: ${{ github.actor }} + password: ${{ github.token }} + registry: ghcr.io + + - name: Build and push raspios bookworm builder + uses: docker/build-push-action@v5 + with: + context: .devcontainer/raspi + file: .devcontainer/raspi/Dockerfile + push: true + tags: ghcr.io/${{ inputs.package-namespace }}/builder-raspios-bookworm:${{ needs.builder-necessary.outputs.builder-tag }} + + build-push-ubuntu: + name: Build and push ubuntu noble (${{ matrix.platform }}) + if: ${{ needs.builder-necessary.outputs.build == 'true' }} + needs: + - builder-necessary + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - platform: amd64 + runner: ${{ github.event.repository.private && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-24.04' }} + - platform: arm64 + runner: ${{ github.event.repository.private && 'buildjet-8vcpu-ubuntu-2204-arm' || 'ubuntu-24.04-arm' }} + + steps: + - name: Checkout the code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Github Registry + uses: docker/login-action@v3 + with: + username: ${{ github.actor }} + password: ${{ github.token }} + registry: ghcr.io + + - name: Build and push ubuntu builder + uses: docker/build-push-action@v5 + with: + context: .devcontainer/ubuntu + file: .devcontainer/ubuntu/Dockerfile + push: true + provenance: false + tags: ghcr.io/${{ inputs.package-namespace }}/builder-ubuntu-noble:${{ needs.builder-necessary.outputs.builder-tag }}-${{ matrix.platform }} + + manifest-ubuntu: + if: ${{ needs.builder-necessary.outputs.build == 'true' }} + needs: + - builder-necessary + - build-push-ubuntu + name: Docker manifest + runs-on: ubuntu-24.04 + + steps: + - name: Login to Github Registry + uses: docker/login-action@v3 + with: + username: ${{ github.actor }} + password: ${{ github.token }} + registry: ghcr.io + + - name: Create and push multiarch manifests + run: | + docker manifest create \ + ghcr.io/${{ inputs.package-namespace }}/builder-ubuntu-noble:${{ needs.builder-necessary.outputs.builder-tag }} \ + ghcr.io/${{ inputs.package-namespace }}/builder-ubuntu-noble:${{ needs.builder-necessary.outputs.builder-tag }}-amd64 \ + ghcr.io/${{ inputs.package-namespace }}/builder-ubuntu-noble:${{ needs.builder-necessary.outputs.builder-tag }}-arm64 + docker manifest push ghcr.io/${{ inputs.package-namespace }}/builder-ubuntu-noble:${{ needs.builder-necessary.outputs.builder-tag }} diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 00000000..4b58923b --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +on: + workflow_call: + inputs: + builder-tag: + description: The builder tag to be used + default: latest + required: false + type: string + ref: + type: string + required: true + package-namespace: + description: The package namespace for docker images + default: ${{ github.repository }} + required: false + type: string + +jobs: + check: + name: Formatting + runs-on: ubuntu-24.04 + container: + image: ghcr.io/${{ inputs.package-namespace }}/builder-ubuntu-noble:${{ inputs.builder-tag}} + options: --user 1001:127 + timeout-minutes: 3 # the worst case is < 1 minute + steps: + - name: Checkout source + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} + + - name: Prepare venv + run: | + python3 -m venv .venv + . .venv/bin/activate && \ + pip install -r docs/requirements.txt + + - name: Check formatting + run: | + . .venv/bin/activate && \ + make -f check.mk check check-docs -j diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..649f69ef --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,135 @@ +# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +name: Main + +on: + pull_request: + types: + - opened + - synchronize + - reopened + - labeled + push: + branches: + - main + workflow_dispatch: + inputs: + ref: + description: The ref sha to checkout evp-agent-oss + type: string + required: false + default: main + package-namespace: + description: The package namespace for docker images + required: true + type: string + + schedule: + - cron: 0 0 * * 1-5 + +concurrency: + group: ${{ github.repository }}-${{ github.workflow }}@main-${{ github.ref }} + cancel-in-progress: true + +jobs: + + infos: + name: Infos + runs-on: ubuntu-24.04 + outputs: + package-namespace: ${{ steps.infos.outputs.namespace }} + steps: + - name: Some infos + id: infos + run: | + echo github.ref is ${{ github.ref }} + echo github.head_ref is ${{ github.head_ref }} + echo github.sha is ${{ github.sha }} + echo github.event_name is ${{ github.event_name }} + echo github.event.pull_request.user.login is ${{ github.event.pull_request.user.login }} + echo github.event.action is ${{ github.event.action }} + echo github.event.repository_owner is ${{ github.repository_owner }} + NAMESPACE=${{ github.repository || github.event.repository }} + NAMESPACE_LC=${NAMESPACE@L} + echo "namespace=${NAMESPACE_LC}" >> $GITHUB_OUTPUT + echo namespace is ${NAMESPACE_LC} + + builder: + name: Builder + needs: + - infos + uses: ./.github/workflows/builder.yml + secrets: inherit + with: + ref: ${{ inputs.ref || github.sha }} + package-namespace: ${{ needs.infos.outputs.package-namespace }} + + checks: + name: Checks + needs: + - builder + - infos + uses: ./.github/workflows/check.yml + secrets: inherit + with: + builder-tag: ${{ needs.builder.outputs.builder-tag }} + ref: ${{ inputs.ref || github.sha }} + package-namespace: ${{ needs.infos.outputs.package-namespace }} + + test-modules: + name: Test-modules + needs: + - checks + - builder + - infos + uses: ./.github/workflows/test-modules.yml + secrets: inherit + with: + builder-tag: ${{ needs.builder.outputs.builder-tag }} + ref: ${{ inputs.ref || github.sha }} + package-namespace: ${{ needs.infos.outputs.package-namespace }} + + build: + name: Build + needs: + - checks + - builder + - infos + uses: ./.github/workflows/build.yml + secrets: inherit + with: + builder-tag: ${{ needs.builder.outputs.builder-tag }} + ref: ${{ inputs.ref || github.sha }} + package-namespace: ${{ needs.infos.outputs.package-namespace }} + + tests: + name: Tests + needs: + - checks + - build + - test-modules + - builder + - infos + uses: ./.github/workflows/test.yml + secrets: inherit + with: + builder-tag: ${{ needs.builder.outputs.builder-tag }} + ref: ${{ inputs.ref || github.sha }} + package-namespace: ${{ needs.infos.outputs.package-namespace }} + + checkpoint-success: + if: ${{ always() }} + runs-on: ubuntu-24.04 + needs: + - tests + steps: + - name: Check all previous jobs finished correctly + run: | + if [ "${{ needs.tests.result }}" = "success" ]; then + echo Requested jobs finished successfully. This PR can be merged + else + echo Requested jobs are failing. This PR can not be merged + exit 1 + fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..f169695c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,153 @@ +# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +name: Release Artifacts + +on: + release: + types: + - published + +jobs: + release-artifacts: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + + - name: Get last successful run id + id: run-id + env: + GH_TOKEN: ${{ github.token }} + run: | + last_run_id=$(gh run list -w main.yml -c ${{ github.sha }} -b main -s completed --json databaseId -L 1 | jq -r .[].databaseId) + test -z $last_run_id && echo "cannot find last successful run_id" && exit 1 || echo "last_run_id=$last_run_id" && echo "last_run_id=$last_run_id" >> $GITHUB_OUTPUT + + - name: Download Python SDK (RaspiOS bookworm ARM64) + uses: actions/download-artifact@v4 + env: + LAST_RUN_ID: ${{ steps.run-id.outputs.last_run_id }} + with: + name: python-sdk-raspios-bookworm-arm64-${{ env.LAST_RUN_ID }} + run-id: ${{ env.LAST_RUN_ID }} + path: dist-raspios-bookworm-arm64 + github-token: ${{ github.event.repository.private && secrets.MIDOJENKINS_ARTIFACT_READ_EVP_AGENT_OSS || github.token }} + + - name: Download Python SDK deb (RaspiOS bookworm ARM64) + uses: actions/download-artifact@v4 + env: + LAST_RUN_ID: ${{ steps.run-id.outputs.last_run_id }} + with: + name: python-sdk-deb-raspios-bookworm-arm64-${{ env.LAST_RUN_ID }} + run-id: ${{ env.LAST_RUN_ID }} + path: dist-raspios-bookworm-arm64 + github-token: ${{ github.event.repository.private && secrets.MIDOJENKINS_ARTIFACT_READ_EVP_AGENT_OSS || github.token }} + + - name: Download Agent deb (RaspiOS bookworm ARM64) + uses: actions/download-artifact@v4 + env: + LAST_RUN_ID: ${{ steps.run-id.outputs.last_run_id }} + with: + name: agent-deb-raspios-bookworm-arm64-${{ env.LAST_RUN_ID }} + run-id: ${{ env.LAST_RUN_ID }} + path: dist-raspios-bookworm-arm64 + github-token: ${{ github.event.repository.private && secrets.MIDOJENKINS_ARTIFACT_READ_EVP_AGENT_OSS || github.token }} + + - name: Download Python SDK (Ubuntu noble ARM64) + uses: actions/download-artifact@v4 + env: + LAST_RUN_ID: ${{ steps.run-id.outputs.last_run_id }} + with: + name: python-sdk-ubuntu-noble-arm64-${{ env.LAST_RUN_ID }} + run-id: ${{ env.LAST_RUN_ID }} + path: dist-ubuntu-noble-arm64 + github-token: ${{ github.event.repository.private && secrets.MIDOJENKINS_ARTIFACT_READ_EVP_AGENT_OSS || github.token }} + + - name: Download Python SDK deb (Ubuntu noble ARM64) + uses: actions/download-artifact@v4 + env: + LAST_RUN_ID: ${{ steps.run-id.outputs.last_run_id }} + with: + name: python-sdk-deb-ubuntu-noble-arm64-${{ env.LAST_RUN_ID }} + run-id: ${{ env.LAST_RUN_ID }} + path: dist-ubuntu-noble-arm64 + github-token: ${{ github.event.repository.private && secrets.MIDOJENKINS_ARTIFACT_READ_EVP_AGENT_OSS || github.token }} + + - name: Download Agent deb (Ubuntu noble ARM64) + uses: actions/download-artifact@v4 + env: + LAST_RUN_ID: ${{ steps.run-id.outputs.last_run_id }} + with: + name: agent-deb-ubuntu-noble-arm64-${{ env.LAST_RUN_ID }} + run-id: ${{ env.LAST_RUN_ID }} + path: dist-ubuntu-noble-arm64 + github-token: ${{ github.event.repository.private && secrets.MIDOJENKINS_ARTIFACT_READ_EVP_AGENT_OSS || github.token }} + + - name: Download Python SDK (Ubuntu noble AMD64) + uses: actions/download-artifact@v4 + env: + LAST_RUN_ID: ${{ steps.run-id.outputs.last_run_id }} + with: + name: python-sdk-ubuntu-noble-amd64-${{ env.LAST_RUN_ID }} + run-id: ${{ env.LAST_RUN_ID }} + path: dist-ubuntu-noble-amd64 + github-token: ${{ github.event.repository.private && secrets.MIDOJENKINS_ARTIFACT_READ_EVP_AGENT_OSS || github.token }} + + - name: Download Python SDK deb (Ubuntu noble AMD64) + uses: actions/download-artifact@v4 + env: + LAST_RUN_ID: ${{ steps.run-id.outputs.last_run_id }} + with: + name: python-sdk-deb-ubuntu-noble-amd64-${{ env.LAST_RUN_ID }} + run-id: ${{ env.LAST_RUN_ID }} + path: dist-ubuntu-noble-amd64 + github-token: ${{ github.event.repository.private && secrets.MIDOJENKINS_ARTIFACT_READ_EVP_AGENT_OSS || github.token }} + + - name: Download Agent deb (Ubuntu noble AMD64) + uses: actions/download-artifact@v4 + env: + LAST_RUN_ID: ${{ steps.run-id.outputs.last_run_id }} + with: + name: agent-deb-ubuntu-noble-amd64-${{ env.LAST_RUN_ID }} + run-id: ${{ env.LAST_RUN_ID }} + path: dist-ubuntu-noble-amd64 + github-token: ${{ github.event.repository.private && secrets.MIDOJENKINS_ARTIFACT_READ_EVP_AGENT_OSS || github.token }} + + - name: Rename deb artifacts + run: | + set -x + for deb in dist-ubuntu-noble-*/*.deb; do + mv $deb $(echo $deb | sed -E 's/(.*)_([^_]*).deb/\1-ubuntu-noble_\2.deb/'); + done + + for deb in dist-raspios-bookworm-*/*.deb; do + mv $deb $(echo $deb | sed -E 's/(.*)_([^_]*).deb/\1-raspios-bookworm_\2.deb/'); + done + + - name: Rename whl artifacts + run: | + set -x + for whl in dist-ubuntu-noble-*/*.whl; do + mv $whl $(echo $whl | sed -E 's/(.*)-([^-]*).whl/\1-ubuntu_noble-\2.whl/'); + done + + for whl in dist-raspios-bookworm-*/*.whl; do + mv $whl $(echo $whl | sed -E 's/(.*)-([^-]*).whl/\1-raspios_bookworm-\2.whl/'); + done + + - name: List files in dist-ubuntu-noble-amd64 + run: ls -la dist-ubuntu-noble-amd64 + + - name: List files in dist-ubuntu-noble-arm64 + run: ls -la dist-ubuntu-noble-arm64 + + - name: List files in dist-raspios-bookworm-arm64 + run: ls -la dist-raspios-bookworm-arm64 + + - name: Push artifacts to release + uses: softprops/action-gh-release@v2 + with: + prerelease: false + files: | + dist-*/*.deb + dist-*/*.whl diff --git a/.github/workflows/test-modules.yml b/.github/workflows/test-modules.yml new file mode 100644 index 00000000..2130c7b3 --- /dev/null +++ b/.github/workflows/test-modules.yml @@ -0,0 +1,79 @@ +# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +name: "WASM and native modules" +on: + workflow_call: + inputs: + ref: + type: string + required: true + builder-tag: + description: The builder tag to be used + default: latest + required: false + type: string + package-namespace: + description: The package namespace for docker images + default: ${{ github.repository }} + required: false + type: string + +jobs: + build-modules: + name: Build modules (${{ matrix.name }}, ${{ matrix.platform }}) + runs-on: ${{ matrix.runner }} + container: + image: ghcr.io/${{ inputs.package-namespace }}/builder-${{ matrix.name }}:${{ inputs.builder-tag }} + credentials: + username: ${{ github.actor }} + password: ${{ github.token }} + options: ${{ startsWith(matrix.runner, 'buildjet') && '--user 1000:1001' || '--user 1001:127' }} + strategy: + fail-fast: false + matrix: + include: + - name: raspios-bookworm + runner: ${{ github.event.repository.private && 'buildjet-4vcpu-ubuntu-2204-arm' || 'ubuntu-24.04-arm' }} + platform: arm64 + - name: ubuntu-noble + runner: ${{ github.event.repository.private && 'buildjet-4vcpu-ubuntu-2204-arm' || 'ubuntu-24.04-arm' }} + platform: arm64 + - name: ubuntu-noble + runner: ${{ github.event.repository.private && 'buildjet-4vcpu-ubuntu-2204' || 'ubuntu-24.04' }} + platform: amd64 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} + + - name: Build all modules + run: | + make -j$((`nproc` * 2)) \ + KBUILD_DEFCONFIG=configs/unit-test-all-hubs-wasm.config \ + wasm_test_modules + make -j$((`nproc` * 2)) -C test_modules/python + + - uses: actions/upload-artifact@v4 + with: + name: test-modules-${{ matrix.name }}-${{ matrix.platform }}-${{ github.run_id }} + path: | + test_modules/*.elf + test_modules/*.wasm + test_modules/*.wasm.* + test_modules/python/*.zip diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..44698686 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,166 @@ +# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +on: + workflow_call: + inputs: + builder-tag: + description: The builder tag to be used + default: ghcr.io/${{ inputs.package-namespace }}/builder-raspios-bookworm + required: false + type: string + ref: + type: string + required: true + package-namespace: + description: The package namespace for docker images + default: ${{ github.repository }} + required: false + type: string + +jobs: + test: + name: Unit tests (${{ matrix.name }}, ${{ matrix.platform }}) + runs-on: ${{ matrix.runner }} + container: + image: ghcr.io/${{ inputs.package-namespace }}/builder-${{ matrix.name }}:${{ inputs.builder-tag }} + credentials: + username: ${{ github.actor }} + password: ${{ github.token }} + options: ${{ startsWith(matrix.runner, 'buildjet') && '--user 1000:1001' || '--user 1001:127' }} + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + include: + - name: raspios-bookworm + runner: ${{ github.event.repository.private && 'buildjet-8vcpu-ubuntu-2204-arm' || 'ubuntu-24.04-arm' }} + platform: arm64 + - name: ubuntu-noble + runner: ${{ github.event.repository.private && 'buildjet-8vcpu-ubuntu-2204-arm' || 'ubuntu-24.04-arm' }} + platform: arm64 + - name: ubuntu-noble + runner: ${{ github.event.repository.private && 'buildjet-4vcpu-ubuntu-2204' || 'ubuntu-24.04' }} + platform: amd64 + + steps: + - name: Checkout source + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} + + - name: Download test modules + uses: actions/download-artifact@v4 + with: + name: test-modules-${{ matrix.name }}-${{ matrix.platform }}-${{ github.run_id }} + path: test_modules/ + + - name: Download Python SDK + uses: actions/download-artifact@v4 + with: + name: python-sdk-${{ matrix.name }}-${{ matrix.platform }}-${{ github.run_id }} + path: py-sdk + + - name: Set permissions + run: chmod +x test_modules/*.elf + + - name: Build dependencies + run: | + make -j$((`nproc` * 2)) \ + KBUILD_DEFCONFIG=configs/unit-test-all-hubs-wasm.config \ + CFLAGS="-g" \ + TOOL=clang \ + depend + + - name: Build agent + run: | + make -j$((`nproc` * 2))\ + KBUILD_DEFCONFIG=configs/unit-test-all-hubs-wasm.config\ + TOOL=clang \ + SANITIZER=ENABLED \ + COVERAGE=ccov \ + CFLAGS="-g -Og -Werror" \ + + - name: Build tests + run: | + make -C test -j$((`nproc` * 2))\ + TOOL=clang \ + SANITIZER=ENABLED \ + COVERAGE=ccov \ + CFLAGS="-g -Og -Werror" \ + LDFLAGS="-fuse-ld=lld -g" \ + build + + - name: Install the Python SDK + run: | + python3 -m venv .venv + . .venv/bin/activate + pip3 install py-sdk/*.whl + + - name: Run tests + env: + ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1 + UBSAN_OPTIONS: print_stacktrace=1 + TERM: xterm + run: . .venv/bin/activate && make -C test -j RUNFLAGS='-c -t 60' + + - name: Print failure logs + if: failure() + run: | + awk '/FAIL/ { + file = FILENAME + sub(/\.res/, ".log", file) + printf("::group::%s[%s] log\n", file, $2) + system("cat " file) + printf("::endgroup::\n") + }' test/logs/*/src/*/*.res + + - name: Generate coverage + run: | + make \ + TOOL=clang \ + COVERAGE=ccov \ + coverage-ci + + - name: Report HTTP upload performance + run: | + ./scripts/print-http-stats.sh >> $GITHUB_STEP_SUMMARY + + # Upload test logs upon failure. + - name: Upload logs + uses: actions/upload-artifact@v4 + if: always() + with: + name: test-log-${{ matrix.name }}-${{ matrix.platform }}-${{ github.run_id }}-${{ github.run_attempt }} + path: test/logs/**/*.log + retention-days: ${{ job.status == 'success' && '7' || '14' }} + + - name: Upload coverage results + uses: actions/upload-artifact@v4 + with: + # Use a specific folder to not overwrite log files + name: coverage-report-${{ matrix.name }}-${{ matrix.platform }}-${{github.run_id}} + path: coverage + retention-days: ${{ job.status == 'success' && '7' || '14' }} + + - name: Report code coverage + if: ${{ matrix.name == 'raspios-bookworm' && matrix.platform == 'arm64' }} + id: report-action-lcov + uses: zgosalvez/github-actions-report-lcov@v4.1.2 + with: + title-prefix: ${{ matrix.name }}-${{ matrix.platform }} + coverage-files: coverage/filtered.lcov + minimum-coverage: 55 + github-token: ${{ github.token }} + update-comment: true + + - name: Report summary coverage to status + if: ${{ matrix.name == 'raspios-bookworm' && matrix.platform == 'arm64' }} + uses: guibranco/github-status-action-v2@v1.1.13 + with: + authToken: ${{ github.token }} + context: "Coverage line level: " + description: ${{ steps.report-action-lcov.outputs.total-coverage }}% + state: success + sha: ${{ github.event.pull_request.head.sha || inputs.ref }} diff --git a/.gitignore b/.gitignore index ccaf2468..8736aeea 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ __pycache__ *.a *.so *.d +*.su /*.tar.gz /*.deb *.whl @@ -52,3 +53,6 @@ analysis.txt .venv/ *.core /dist +/src/sdkenc/stamp +/src/sdkenc/*.h +/include/sdkenc/*.h diff --git a/.gitmodules b/.gitmodules index d442db6f..f14d4c33 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,9 +2,6 @@ # # SPDX-License-Identifier: Apache-2.0 -[submodule "src/nng"] - path = src/nng - url = https://github.com/nanomsg/nng.git [submodule "src/mbedtls"] path = src/mbedtls url = https://github.com/Mbed-TLS/mbedtls.git diff --git a/.readthedocs.yaml b/.readthedocs.yaml index d7803d2b..336f54dd 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -5,7 +5,7 @@ version: "2" build: - os: "ubuntu-22.04" + os: "ubuntu-24.04" tools: python: "3.10" diff --git a/Makefile b/Makefile index 2685088e..cc8efc2c 100644 --- a/Makefile +++ b/Makefile @@ -70,12 +70,14 @@ deps.mk: .config dist: all $(SCRIPTDIR)/mk-agent-deb.sh -V $(VERSION) -a $(ARCH) + $(SCRIPTDIR)/mk-sdk-deb.sh -V $(SDK_VERSION) -a $(ARCH) clean: cd test && $(MAKE) clean rm -rf bin lib - rm -rf include/nng include/psa + rm -rf include/psa rm -rf include/flatcc include/mbedtls + rm -rf include/sdkenc rm -rf include/lib_export.h include/version.h include/parson.h rm -f include/wasm_c_api.h include/wasm_export.h rm -f libevp-app-sdk-*.tar.gz libevp-app-sdk-*.deb diff --git a/configs/linux-multi-privman-keylog.config b/configs/linux-multi-privman-keylog.config index 51e060fa..01e46d89 100644 --- a/configs/linux-multi-privman-keylog.config +++ b/configs/linux-multi-privman-keylog.config @@ -1,6 +1,5 @@ CONFIG_EVP_AGENT_BOARD_SUPPORT="configs/defaults.mk" CONFIG_EVP_AGENT_EXPERIMENTAL=y -CONFIG_EVP_AGENT_LOCAL_SDK_NNG_STREAMS=y CONFIG_EVP_AGENT_MODULE_IMPL_DOCKER_NO_IMAGE_PRUNE=y CONFIG_EVP_AGENT_MODULE_IMPL_DOCKER_RAW_CONTAINER_SPEC=y CONFIG_EVP_AGENT_TLS_KEYLOG=y diff --git a/configs/nuttx.config b/configs/nuttx.config index 38761fc4..d9822616 100644 --- a/configs/nuttx.config +++ b/configs/nuttx.config @@ -313,8 +313,6 @@ CONFIG_INIT_ENTRY=y CONFIG_INIT_ARGS="" CONFIG_INIT_STACKSIZE=8192 CONFIG_INIT_PRIORITY=100 -# TODO when midokura repo is up to date, this line should be removed -CONFIG_USER_ENTRYPOINT="nsh_main" CONFIG_INIT_ENTRYPOINT="nsh_main" CONFIG_INIT_ENTRYNAME="nsh_main" CONFIG_RR_INTERVAL=200 @@ -1398,7 +1396,6 @@ CONFIG_EVP_AGENT_MODULE_LOG_REPORT_LEN=4096 CONFIG_EVP_AGENT_MODULE_LOG_REPORT_PERIOD=1000 CONFIG_EXTERNALS_MBEDTLS=y CONFIG_EVP_AGENT_BOARD_SUPPORT="configs/defaults.mk" -CONFIG_EVP_AGENT_LOCAL_SDK_NNG_STREAMS=y CONFIG_EVP_BLOB_GET_UPLOAD_URL=y # @@ -1780,5 +1777,3 @@ CONFIG_READLINE_MAX_EXTCMDS=64 # CONFIG_IEEE802154_I8SAK is not set # CONFIG_IEEE802154_LIBMAC is not set # CONFIG_IEEE802154_LIBUTILS is not set - -CONFIG_NETUTILS_NNG=y diff --git a/configs/sdk-linux.config b/configs/sdk-linux.config index 7e92fb73..96ca4549 100644 --- a/configs/sdk-linux.config +++ b/configs/sdk-linux.config @@ -1,3 +1,2 @@ CONFIG_EVP_AGENT_BOARD_SUPPORT="configs/defaults.mk" -CONFIG_EVP_AGENT_LOCAL_SDK_NNG_STREAMS=y CONFIG_EVP_SDK_SOCKET=y diff --git a/configs/unit-test-all-hubs-wasm.config b/configs/unit-test-all-hubs-wasm.config index 92f6c97b..7f68843d 100644 --- a/configs/unit-test-all-hubs-wasm.config +++ b/configs/unit-test-all-hubs-wasm.config @@ -3,7 +3,6 @@ CONFIG_EVP_AGENT_BOARD_SUPPORT="configs/defaults.mk" CONFIG_EVP_AGENT_EXPERIMENTAL=y -CONFIG_EVP_AGENT_LOCAL_SDK_NNG_STREAMS=y CONFIG_EVP_AGENT_MAX_LIVE_BLOBS_PER_INSTANCE=3 CONFIG_EVP_AGENT_MODULE_IMPL_DOCKER_RAW_CONTAINER_SPEC=y CONFIG_EVP_BLOB_GET_UPLOAD_URL=y diff --git a/docs/README.md b/docs/README.md index ce4a92fa..29fbd6f4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,7 +13,7 @@ Edge Virtualization Platform (EVP) project. ## Building the documentation The latest documentation of EVP -can always be found in [Midokura EVP Agent documentation], +can always be found in [EVP Agent documentation], built automatically through [Read the Docs] for every update of any branch. Additionally, the documentation @@ -121,7 +121,7 @@ under the Apache-2.0 License. See `LICENSE` in repository root for details. [Sphinx]: https://www.sphinx-doc.org/en/master -[Midokura EVP Agent documentation]: https://midokura-edge-virtualization-platform.readthedocs-hosted.com/en/latest/about/agent_features.html +[EVP Agent documentation]: https://evp-agent.docs.midokura.com/en/latest/ [Read the Docs]: https://readthedocs.com [Python Developer’s Guide for documenting]: https://devguide.python.org/documentation/markup/#sections [Semantic Linefeeds]: https://rhodesmill.org/brandon/2012/one-sentence-per-line diff --git a/docs/about/release_process.rst b/docs/about/release_process.rst index 07d13385..1c8501ce 100644 --- a/docs/about/release_process.rst +++ b/docs/about/release_process.rst @@ -22,7 +22,7 @@ In order to create a new release, firstly it is necessary to bump the version of the different relevant artifacts: -- ``scripts/rules.mk`` (agent) +- ``scripts/rules.mk`` (agent and C SDK) - ``version.mk`` (agent deprecated) - ``src/python-evp-app-sdk/setup.py`` (Python App SDK) @@ -31,7 +31,7 @@ targetting the ``main`` branch. The tag ``releases/v`` with the same value from ``scripts/rules.mk`` must be created. The field version is the value defined in ``rules.mk`` -where ``version`` must following `semantic versioning`_. +where ``version`` must follow `semantic versioning`_. The release process is thoroughly documented by `GitHub`_. diff --git a/docs/conf.py b/docs/conf.py index 75b51b52..0dd71bb7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -9,10 +9,7 @@ import re project = "EVP Agent" -copyright = ( - "2025, Sony Semiconductor Solutions Corporation. " - + "Sony Semiconductor Solutions Confidential" -) +copyright = "2025, Sony Semiconductor Solutions Corporation." author = "Sony Semiconductor Solutions Corporation" version = "unknown-dev" version_re = re.compile(r"^VERSION\s*=\s*(.*)\s*$") @@ -35,6 +32,7 @@ "sphinx.ext.doctest", "sphinx.ext.autodoc", "sphinx.ext.autosummary", + "sphinx_copybutton", "sphinx.ext.intersphinx", ] diff --git a/docs/design/architecture.rst b/docs/design/architecture.rst index 7e2ff581..ea81a372 100644 --- a/docs/design/architecture.rst +++ b/docs/design/architecture.rst @@ -2,6 +2,8 @@ .. .. SPDX-License-Identifier: Apache-2.0 +.. _design/architecture: + Architecture of the agent ######################### @@ -95,7 +97,7 @@ Config The agent supports definining key/value pairs to configure EVP module instances. Module instances can subscribe to configurations -via ``EVP_setConfigurationCallback``. +via :c:func:`EVP_setConfigurationCallback`. Module instance configuration is implemented by ``src/libevp-agent/instance_config.c``, and is processed according to the configured version of the EVP protocol. diff --git a/docs/design/index.rst b/docs/design/index.rst index f28dc832..705fc6e4 100644 --- a/docs/design/index.rst +++ b/docs/design/index.rst @@ -5,6 +5,103 @@ System Design ############# +Introduction +============ + +The Edge Virtualization Platform Agent +is designed as a series of loosely coupled components +that interact with each other to allow the orchestration +and management of workloads in the Edge device. + +Controller interface (HUB) +========================== + +The agent connects to a controller hub, which can send +deployment manifests and other messages to instantiate +and control modules and module instances. + +The module instances' lifecycles +are always managed by the Agent as +behavioral response +to a new deployment manifest from the Hub. +The Hub is the source of truth +about the desired deployment that runs on the device. + +Whenever the Agent receives a new desired deployment from the hub, +It will "reconcile" the current and desired deployments, +and ultimately start/stop the relevant modules, +that were added or removed, +while maintaining the state of the modules and instances +that did not change. + +The hub interface is designed as a common interface, +so that different onwire-schemas and protocols +can be easily added. + +The agent supports +the deprecated EVP1 +and the new EVP2 hub interfaces, +which is the default, +MQTT-based schema +that is used by the hub +to control the Agent. + +More information can be found in :ref:`design/architecture`. + +Applications, module instances types and APIs +============================================= + +There are two implementations to communicate with module instances: +the local implementation (sometimes called Local SDK) and the remote +implementation (sometiems called Remote SDK). +Although, these offer the same interface, +the underlying communication mechanisms are different. + +The local implementation is to be used +with modules and instances +that share the same process as the agent. +These are usually run in a pthread inside the agent task. +This is essentially used for wasm modules, since we include the +WAMR runtime in the Agent, we start WASM modules in a thread, and +they can communicate with the agent by direct function calls and pointers. + +The remote implementation is to be used +with modules and instances +that run in a separate process from the Agent. +This is the case for docker, spawn and python modules. +Since for these modules, the runtime is not embedded in the agent, +a RPC-like flatbuffer interface over a UNIX domain socket is used. + +These full featured interfaces offer +a variety of networking functionalities +to the module instances. +More information can be found in :ref:`application_sdk`. + +System Application Interfaces +============================= + +In some devices, +it is desirable +to have applications that control the system, +to handle workflows like reboot, OTA, configuration management, etc. + +Since these applications lifecycle are not managed by the hub, +these are not Modules or Module instances. +They are not tracked in the deployment manifest or status. + +These applications are started by the agent executable, +especially when a custom main program is linked using :ref:`embedding`. +and usually run in a pthread. + +The SystemApps can use the EVP features +available in :ref:`evp-systemapp_sdk`, +on behalf of the device. + +Also since they do not have module instances IDs, +all the operations are done on behalf of the device. + +More information can be found in :ref:`evp-systemapp_sdk` + .. toctree:: :maxdepth: 1 diff --git a/docs/getting_started/build_sys/rules.mk.rst b/docs/getting_started/build_sys/rules.mk.rst index b9c1950f..a1607cf3 100644 --- a/docs/getting_started/build_sys/rules.mk.rst +++ b/docs/getting_started/build_sys/rules.mk.rst @@ -396,7 +396,6 @@ that enables actions such as: wasm-micro-runtime: wasm-micro-runtime/build/Makefile flatcc: flatcc/build/Makefile mbedtls: mbedtls/build/Makefile - nng: nng/build/Makefile that will generate a chain of dependencies which will compile correctly a `CMake`_ project diff --git a/docs/getting_started/prerequisites.rst b/docs/getting_started/prerequisites.rst index 229b6086..f6dff637 100644 --- a/docs/getting_started/prerequisites.rst +++ b/docs/getting_started/prerequisites.rst @@ -62,7 +62,6 @@ It also requires the following libraries: * `WAMR`_ 2.1.2 * `MbedTLS`_ 3.6.2 - * `Nanomsg-ng`_ 1.7.3 * `Flatcc`_ 0.6.1 All these libraries are shipped as :ref:`git_submodules` within @@ -144,7 +143,6 @@ repository, that can be cloned using: .. _Python3: https://www.python.org .. _WAMR: https://bytecodealliance.github.io/wamr.dev .. _MbedTLS: https://www.trustedfirmware.org/projects/mbed-tls -.. _Nanomsg-ng: https://nng.nanomsg.org .. _Flatcc: https://github.com/dvidelabs/flatcc .. _Github: https://www.github.com .. _WASI-SDK: https://github.com/WebAssembly/wasi-sdk diff --git a/docs/getting_started/source_tree.rst b/docs/getting_started/source_tree.rst index ae78746b..48dfb8c7 100644 --- a/docs/getting_started/source_tree.rst +++ b/docs/getting_started/source_tree.rst @@ -51,7 +51,6 @@ Key directories and files - ``libevp-app-sdk/``: EVP Application SDK for modules. - ``libevp-utils/``: Utility functions for the EVP project. - ``mbedtls/``: Lightweight cryptographic library (git module). - - ``nng/``: Lightweight messaging library (git module). - ``python-evp-app-sdk/``: Python version sources of the EVP Application SDK. - ``wasm-micro-runtime/``: WebAssembly Micro Runtime integration (git module). - ``evp-agent/``: The runtime of the default EVP Agent. diff --git a/docs/interfaces/application_sdk/base.rst b/docs/interfaces/application_sdk/base.rst new file mode 100644 index 00000000..05c6b8b7 --- /dev/null +++ b/docs/interfaces/application_sdk/base.rst @@ -0,0 +1,923 @@ +.. SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +.. +.. SPDX-License-Identifier: Apache-2.0 + +Base +#### + +Types +***** + +.. c:struct:: EVP_client + + An opaque structure + to represent an EVP client. + + This client is used + by EVP module instances + to communicate with + the EVP agent running locally + on the same device. + + An EVP module instance + can obtain the pointer + to the client + by calling :c:func:`EVP_initialize`. + + The majority of SDK API functions + take a pointer to this structure. + + +.. c:type:: EVP_RESULT + + The type to represent either + a success or an error. + Used as the return value of + several of the functions in this SDK. + + :values: + + .. c:enumerator:: EVP_OK + + :value: 0 + + At least one event has been processed. + + .. c:enumerator:: EVP_SHOULDEXIT + + :value: 1 + + The module instance is requested to stop. + It should exit performing cleanup + as soon as possible. + + .. c:enumerator:: EVP_TIMEDOUT + + :value: 2 + + The specified period has elapsed without any events. + + .. c:enumerator:: EVP_ERROR + + :value: 3 + + An error ocurred. + + .. c:enumerator:: EVP_INVAL + + :value: 4 + + Invalid parameter. + + .. c:enumerator:: EVP_NOMEM + + :value: 5 + + Memory allocation failed. + + .. c:enumerator:: EVP_TOOBIG + + :value: 6 + + Too big payload. + + .. c:enumerator:: EVP_AGAIN + + :value: 7 + + Failure because of temporary conditions. + + .. c:enumerator:: EVP_AGENT_PROTOCOL_ERROR + + :value: 8 + + Protocol error when communicating with the agent. + + .. c:enumerator:: EVP_EXIST + + :value: 9 + + The request failed bacause of + conflicting existing entries. + + + .. c:enumerator:: EVP_FAULT + + :value: 10 + + Invalid address was detected. + + .. note:: + + An application should not rely on such a detection. + It's the responsibility of applications to always specify + vaild addresses. + + .. c:enumerator:: EVP_DENIED + + :value: 11 + + A request was denied. + It could mean the agent cannot be + transmitting due to a full queue. + + + .. c:enumerator:: EVP_NOTSUP + + :value: 12 + + The request is still not supported by + the implementation. + +.. c:type:: uint64_t EVP_RPC_ID + + The integer request ID used for RPCs. + +Reasons +======= + +Each callback type have its associated +``EVP_*_CALLBACK_REASON`` enum. + +They share some common definitions: + +.. c:enumerator:: CALLBACK_REASON_SENT + + The request has been received by + the next hop entity. + (Typically the agent within the device. + It will try its best to + deliver the State to + the Cloud reliably.) + + .. note:: + + This doesn't mean the State has reached the Cloud. + +.. c:enumerator:: CALLBACK_REASON_EXIT + + The request has been cancelled because + the module instance is going to exit. + This gives the module instance + a chance to cleanup + the associated resources before exiting. + + Users must not send any more requests + to the agent when this code is received, + and instead must call + :c:func:`EVP_processEvent` until + all events are flushed. + +.. c:enumerator:: CALLBACK_REASON_ERROR + + The request has not been processed + because it is invalid. + +.. c:enumerator:: CALLBACK_REASON_DENIED + + A request was denied for transmission. + This means the agent could not enqueue + the request due to a full queue. + +.. c:type:: EVP_STATE_CALLBACK_REASON + + The type to represent the reason of the callback invocation. + + :values: + + .. c:enumerator:: EVP_STATE_CALLBACK_REASON_SENT + + :value: 0 + + See :c:enumerator:`CALLBACK_REASON_SENT`. + + .. c:enumerator:: EVP_STATE_CALLBACK_REASON_OVERWRITTEN + + :value: 1 + + The State has been overwritten by + another :c:func:`EVP_sendState` call with + the same topic. + + .. note:: + + The SDK only cares about + the latest State for a topic. + + .. c:enumerator:: EVP_STATE_CALLBACK_REASON_EXIT + + :value: 2 + + See :c:enumerator:`CALLBACK_REASON_EXIT`. + + .. c:enumerator:: EVP_STATE_CALLBACK_REASON_DENIED + + :value: 3 + + See :c:enumerator:`CALLBACK_REASON_DENIED`. + +.. c:type:: EVP_MESSAGE_SENT_CALLBACK_REASON + + The type to represent the reason of the callback invocation. + + :values: + + .. c:enumerator:: EVP_MESSAGE_SENT_CALLBACK_REASON_SENT + + :value: 0 + + See :c:enumerator:`CALLBACK_REASON_SENT`. + + .. c:enumerator:: EVP_MESSAGE_SENT_CALLBACK_REASON_ERROR + + :value: 1 + + See :c:enumerator:`CALLBACK_REASON_ERROR`. + + + .. c:enumerator:: EVP_MESSAGE_SENT_CALLBACK_REASON_EXIT + + :value: 2 + + See :c:enumerator:`CALLBACK_REASON_EXIT`. + +.. c:type:: EVP_TELEMETRY_CALLBACK_REASON + + The type to represent the reason of the callback invocation. + + :values: + + .. c:enumerator:: EVP_TELEMETRY_CALLBACK_REASON_SENT + + :value: 0 + + See :c:enumerator:`CALLBACK_REASON_SENT`. + + .. c:enumerator:: EVP_TELEMETRY_CALLBACK_REASON_ERROR + + :value: 1 + + See :c:enumerator:`CALLBACK_REASON_ERROR`. + + .. c:enumerator:: EVP_TELEMETRY_CALLBACK_REASON_EXIT + + :value: 2 + + See :c:enumerator:`CALLBACK_REASON_EXIT`. + + .. c:enumerator:: EVP_TELEMETRY_CALLBACK_REASON_DENIED + + :value: 3 + + See :c:enumerator:`CALLBACK_REASON_DENIED`. + +.. c:type:: EVP_RPC_RESPONSE_CALLBACK_REASON + + The type to represent the reason of the callback invocation. + + :values: + + .. c:enumerator:: EVP_RPC_RESPONSE_CALLBACK_REASON_SENT + + :value: 0 + + See :c:enumerator:`CALLBACK_REASON_SENT`. + + .. c:enumerator:: EVP_RPC_RESPONSE_CALLBACK_REASON_ERROR + + :value: 1 + + See :c:enumerator:`CALLBACK_REASON_ERROR`. + + .. c:enumerator:: EVP_RPC_RESPONSE_CALLBACK_REASON_EXIT + + :value: 2 + + See :c:enumerator:`CALLBACK_REASON_EXIT`. + + .. c:enumerator:: EVP_RPC_RESPONSE_CALLBACK_REASON_DENIED + + :value: 3 + + See :c:enumerator:`CALLBACK_REASON_DENIED`. + + +.. c:type:: EVP_RPC_RESPONSE_STATUS + + The type to specify a status condition for a RPC response to the Hub. + + :values: + + .. c:enumerator:: EVP_RPC_RESPONSE_STATUS_OK + + :value: 0 + + The RPC request executed successfully and the response + contains the results of the execution. + + .. c:enumerator:: EVP_RPC_RESPONSE_STATUS_METHOD_NOT_FOUND + + :value: 1 + + The originating RPC request specified a method that is not + implemented, so it is reported back as not found. + + .. c:enumerator:: EVP_RPC_RESPONSE_STATUS_ERROR + + :value: 2 + + The RPC request executed with error and the response + contains the error message + +.. c:type:: EVP_WORKSPACE_TYPE + + + The type to represent a workspace type. + + :values: + + .. c:enumerator:: EVP_WORKSPACE_TYPE_DEFAULT + + :value: 0 + + Default type of Workspace. + +.. c:type:: int EVP_STREAM + + The type used to represent a stream. + +.. c:type:: unsigned long EVP_STREAM_PEER_ID + + The type used to represent a peer identifier. + +Callbacks +========= + +.. c:type:: void (*EVP_CONFIGURATION_CALLBACK)(const char *topic, const void *config, size_t configlen, void *userData) + + Function prototype for the callback passed to the function + :c:func:`EVP_setConfigurationCallback`. + + **Parameters**: + - **topic** - Destination topic. + - **config** - The buffer to pass as configuration. + - **configlen** - The size of the configuration data for sending. + - **userData** - An arbitrary blob of data to pass to the callback. + +.. c:type:: void (*EVP_STATE_CALLBACK)(EVP_STATE_CALLBACK_REASON reason, void *userData) + + Function prototype for the callback passed to State message-dealing + functions such as :c:func:`EVP_sendState`. + + **Parameters**: + - **reason** - The cause code for executing the callback. + - **userData** - An arbitrary blob of data to pass to the callback. + +.. c:type:: void (*EVP_MESSAGE_SENT_CALLBACK)(EVP_MESSAGE_SENT_CALLBACK_REASON reason, void *userData) + + Function prototype for the callback passed to generic message-dealing + functions such as :c:func:`EVP_sendMessage`. + + **Parameters**: + - **reason** - The cause code for executing the callback. + - **userData** - An arbitrary blob of data to pass to the callback. + +.. c:type:: void (*EVP_MESSAGE_RECEIVED_CALLBACK)(const char *topic, const void *msgPayload, size_t msgPayloadLen, void *userData) + + Function prototype for the callback passed to the function + :c:func:`EVP_setMessageCallback`. Executed when a message is received + on the configured ``topic``. + + **Parameters**: + - **topic** - Destination topic. + - **msgPayload** - The buffer to pass as configuration. + - **msgPayloadLen** - The size of the configuration data for sending. + - **userData** - An arbitrary blob of data to pass to the callback. + +.. c:type:: void (*EVP_TELEMETRY_CALLBACK)(EVP_TELEMETRY_CALLBACK_REASON reason, void *userData) + + Function prototype for the callback passed to :c:func:`EVP_sendTelemetry`. + + **Parameters**: + - **reason** - The cause code for executing the callback. + - **userData** - An arbitrary blob of data to pass to the callback. + +.. c:type:: void (*EVP_RPC_REQUEST_CALLBACK)(EVP_RPC_ID id, const char *methodName, const char *params, void *userData) + + Function prototype for the callback passed to :c:func:`EVP_setRpcCallback`. + + **Parameters**: + - **id** - The request Id for :c:func:`EVP_sendRpcResponse`. + - **methodName** - The name of method. + - **params** - The call parameters. A string representation of + a JSON value. + +.. c:type:: void (*EVP_RPC_RESPONSE_CALLBACK)(EVP_RPC_RESPONSE_CALLBACK_REASON reason, void *userData) + + Function prototype for the callback passed to :c:func:`EVP_sendRpcResponse`. + + **Parameters**: + - **reason** - The cause code for executing the callback. + - **userData** - An arbitrary blob of data to pass to the callback. + +.. c:type:: void (*EVP_STREAM_READ_CALLBACK)(EVP_STREAM_PEER_ID id, const void *buf, size_t n, void *userData) + + The callback type used to represent a read-available stream + operation. + + **Parameters**: + - **id** - Peer identifier. Whereas this remains as an + opaque type, applications can rely on + different identifiers meaning different connections to a given stream. + - **buf** - Buffer containing the input data. + - **n** - Buffer length. + - **userData** - An opaque pointer to user-defined data, + as defined by :c:func:`EVP_streamInputOpen` . + +Functions +********* + +.. c:function:: struct EVP_client *EVP_initialize(void) + + Initialize the SDK. + + Performs the required initialization operations + for the module instance. + + This should be called by the main thread + of the module instance. + Otherwise, the behaviour is undefined. + + This should not be called more than once + for a module instance. + Otherwise, the behaviour is undefined. + + :returns: Client object pointer for the calling module instance. + +.. c:function:: const char EVP_getWorkspaceDirectory(struct EVP_client *h, EVP_WORKSPACE_TYPE type) + + Returns the absolute path of the workspace directory + for the calling Module Instance. + + The workspace directory with the default type + (:c:enumerator:`~EVP_WORKSPACE_TYPE.EVP_WORKSPACE_TYPE_DEFAULT`) + has the following characteristics: + + - Initially, the workspace directory is empty. + + - The workspace directory is left intact + across a reboot of the Module + Instace and/or the device. + It can contain the contents left by the + Module Instance before a reboot. + + - The Module Instance has an exclusive access + to its workspace directory + during its lifetime. + + - The Module Instance can access + the workspace directory directly, + using the OS interfaces like + :c:func:`open` and :c:func:`mkdir`. + + - The Module Instance can request file operations + on the workspace directory via the SDK. + For example, + upload from/download to a file + on the workspace directory. + + - The Module Instance should only use + regular files and directories on + the workspace directory. + If it attempts to create other file types, + the behavior is undefined. + + - The agent will remove files + in the workspace directory after + the corresponding Module Instance has gone away. + That is, + at some point + after a successful deployment + of a new Deployment which doesn't contain + the Module Instance anymore. + + :param h: Client object pointer. + :param type: Workspace type + + :returns: The absolute path to the workspace directory. + +.. c:function:: EVP_RESULT EVP_setConfigurationCallback(struct EVP_client *h, EVP_CONFIGURATION_CALLBACK cb, void *userData) + + Register a callback function for Configuration. + + This should not be called more than once for + a :c:struct:`EVP_client` object. + Otherwise, the behaviour is undefined. + + The callback :c:var:`cb` will be called in + the context of this function or of + :c:func:`EVP_processEvent`. + + The callback will be called + on the following events at least: + + - When the callback function is registered. + - When the SDK received the latest Configuration. + + The SDK might coalesce multiple events into one. + In that case, + the callback will be called with + the latest Configuration. + + The SDK might choose to invoke + this callback more frequently than necessary. + The callback function should not assume that + the given Configuration was updated. + + All pointers given to the callback, + including topic and Configuration, + are only valid until the callback function returns. + The callback function should make a copy if necessary. + + :param h: Client object pointer. + :param cb: User callback function. + :param userData: The SDK passes this value to the callback as it is. + The SDK doesn't care if it's a valid pointer. + + :returns: :c:enumerator:`~EVP_RESULT.EVP_OK` on Success. + +.. c:function:: EVP_RESULT EVP_sendState(struct EVP_client *h, const char *topic, const void *state, size_t statelen, EVP_STATE_CALLBACK cb, void *userData) + + Schedule to send the specified State for the specified topic. + + The callback :c:var:`cb` will be called + in the context of this function or of + :c:func:`EVP_processEvent`, + when the request has been sent or cancelled. + It will be invoked with one of + the reasons defined by + :c:enum:`EVP_STATE_CALLBACK_REASON`. + + .. warning:: + + It's the caller's responsibility + to keep the specified :c:var:`topic` and :c:var:`state` + valid until the callback is called. + Otherwise, the behaviour is undefined. + (The SDK implementation might choose + to keep pointers of them + without making copies.) + + :param h: Client object pointer. + :param topic: Destination topic. + :param state: State data. + :param statelen: State size in bytes. + :param cb: User callback function. + :param userData: The SDK passes this value to the callback as it is. + The SDK doesn't care if it's a valid pointer. + + :returns: :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + +.. c:function:: EVP_RESULT EVP_sendMessage(struct EVP_client *h, const char *topic, const void *state, size_t statelen, EVP_MESSAGE_SENT_CALLBACK cb, void *userData) + + Schedule to send the specified message. + + The callback will be called + in the context of this function or of + :c:func:`EVP_processEvent`, + when the request has been sent or cancelled. + It will be invoked with one of + the reasons defined by + :c:enum:`EVP_MESSAGE_SENT_CALLBACK_REASON`. + + .. warning:: + + It's the caller's responsibility + to keep the specified :c:var:`topic` and :c:var:`state` + valid until the callback is called. + Otherwise, the behaviour is undefined. + (The SDK implementation might choose + to keep pointers of them + without making copies.) + + :param h: Client object pointer. + :param topic: Destination topic. + :param state: State data. + :param statelen: State size in bytes. + :param cb: User callback function. + :param userData: The SDK passes this value to the callback as it is. + The SDK doesn't care if it's a valid pointer. + + :returns: :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + + +.. c:struct:: EVP_telemetry_entry + + Describe a telemetry data + + A Key-Value pair to be sent as a telemetry. + Both of the key and value should be a valid UTF-8 string. + The value should be a string representation of a valid JSON value. + + .. c:member:: const char *key + + A key + + .. c:member:: const char *value + + A JSON value + +.. c:function:: EVP_RESULT EVP_sendTelemetry(struct EVP_client *h, const struct EVP_telemetry_entry *entries, size_t nentries, EVP_TELEMETRY_CALLBACK cb, void *userData) + + Schedule to send the telemetry. + + The callback will be called + in the context of this function or of + :c:func:`EVP_processEvent`, + when the request has been sent or cancelled. + It will be invoked with one + of the reasons defined by + :c:enum:`EVP_TELEMETRY_CALLBACK_REASON`. + + .. warning:: + + It's the caller's responsibility + to keep the specified :c:var:`entries` + valid until the callback is called. + Otherwise, the behaviour is undefined. + (The SDK implementation might choose + to keep pointers of them + without making copies.) + + :param h: Client object pointer. + :param entries: The array of the telemetry data. + :param nentries: The size of the array. + :param cb: User callback function. + :param userData: The SDK passes this value to the callback as it is. + The SDK doesn't care if it's a valid pointer. + + :returns: :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + +.. c:function:: EVP_RESULT EVP_processEvent(struct EVP_client *h, int timeout_ms) + + Wait for an event and process it. + + This function is intended to be called in the main loop of + the module instance. + It waits for an event (e.g. Configuration update) and process it. + It processes one pending event per call. + + :param h: Client object pointer. + + :param milliseconds: + - 0 means immediate. + - -1 means forever. + + :returns: + + - :c:enumerator:`~EVP_RESULT.EVP_OK` + When at least one event has been processed. + - :c:enumerator:`~EVP_RESULT.EVP_TIMEDOUT` + When the period specified by `timeout_ms` + has elapsed without any events. + - :c:enumerator:`~EVP_RESULT.EVP_SHOULDEXIT` + When the module instance is requested to stop + and all events have been already dispatched. + It should exit performing cleanup as soon as + possible. + + See + :c:enumerator:`~EVP_STATE_CALLBACK_REASON.EVP_STATE_CALLBACK_REASON_EXIT`, + :c:enumerator:`~EVP_MESSAGE_SENT_CALLBACK_REASON.EVP_MESSAGE_SENT_CALLBACK_REASON_EXIT`, + :c:enumerator:`~EVP_TELEMETRY_CALLBACK_REASON.EVP_TELEMETRY_CALLBACK_REASON_EXIT`, + :c:enumerator:`~EVP_RPC_RESPONSE_CALLBACK_REASON.EVP_RPC_RESPONSE_CALLBACK_REASON_EXIT`, + :c:enumerator:`~EVP_BLOB_CALLBACK_REASON.EVP_BLOB_CALLBACK_REASON_EXIT` + +.. c:function:: EVP_RESULT EVP_setMessageCallback(struct EVP_client *h, EVP_MESSAGE_RECEIVED_CALLBACK incoming_cb, void *userData) + + Specifies a callback to invoke + on every incoming message. + + This should not be called more than once + for a :c:struct:`EVP_client`. + Otherwise, the behaviour is undefined. + + The callback will be called + in the context of :c:func:`EVP_processEvent`, + upon reception of a message + on any of the subscribed topics. + + .. note:: + + Messages which have arrived + before a successful call to + this function might or might not be + delivered to the specified callback. + + :param h: Client object pointer. + :param incoming_cb: User callback function. + :param userData: The SDK passes this value to the callback as it is. + The SDK doesn't care if it's a valid pointer. + + :returns: :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + +.. c:function:: EVP_RESULT EVP_setRpcCallback(struct EVP_client *h, EVP_RPC_REQUEST_CALLBACK cb, void *userData) + + Specifies a callback to invoke on every incoming RPC call. + + This should not be called more than once for a :c:struct:`EVP_client`. + Otherwise, the behaviour is undefined. + + The callback will be called + in the context of :c:func:`EVP_processEvent`, + upon reception of a RPC request. + + .. note:: + + RPC calls which have arrived + before a successful call of + this function might or might not be delivered + to the specified callback. + + For each invocation of the specified callback, + :c:func:`EVP_sendRpcResponse` should be called + exactly once with the ID given by the callback + and Client object pointer specified to + this function. + It's the caller's responsibility to ensure that. + Otherwise, the behaviour is undefined. + + :param h: Client object pointer. + :param cb: User callback function. + :param userData: The SDK passes this value to the callback as it is. + The SDK doesn't care if it's a valid pointer. + + :returns: :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + +.. c:function:: EVP_RESULT EVP_sendRpcResponse(struct EVP_client *h, EVP_RPC_ID id, const char *response, EVP_RPC_RESPONSE_STATUS status, EVP_RPC_RESPONSE_CALLBACK cb, void *userData) + + Schedule to send the specified RPC response. + + This function can be used within the context of + :c:type:`EVP_RPC_REQUEST_CALLBACK`. + + The callback will be called + in the context of this function or + of :c:func:`EVP_processEvent`, + when the request has been sent or cancelled. + It will be invoked with one + of the reasons defined by + :c:enum:`EVP_RPC_RESPONSE_CALLBACK_REASON`. + + For implementing named methods, + the SDK provides a method-not-found response + by setting the status flag to + :c:enumerator:`~EVP_RPC_RESPONSE_STATUS.EVP_RPC_RESPONSE_STATUS_METHOD_NOT_FOUND`. + In that case, + the value of :c:var:`response` + will be ignored. + + See the entire set of values + of :c:enum:`EVP_RPC_RESPONSE_STATUS` + to use in other situations. + + It's the caller's responsibility + to keep the specified parameters valid + until the callback is called. + Otherwise, the behavior is undefined + (The SDK implementation might choose + to keep pointers of them + without making copies). + + :param h: Client object pointer. + :param id: The request ID from :c:enum:`EVP_RPC_REQUEST_CALLBACK`, + to which you want to reply. + :param response: The response. + It should be a string representation of + a valid JSON value. + :param status: Response status. + :param cb: User callback function. + :param userData: The SDK passes this value to the callback as it is. + The SDK doesn't care if it's a valid pointer. + + :returns: + + - :c:enumerator:`~EVP_RESULT.EVP_OK` + in case of success. + - :c:enumerator:`~EVP_RESULT.EVP_TOOBIG` + when the payload is larger than the agent + can handle (i.e. due to device constraints). + - :c:enumerator:`~EVP_RESULT.EVP_INVAL` + if the response is NULL. + +.. c:function:: EVP_RESULT EVP_streamOutputOpen(struct EVP_client *h, const char *name, EVP_STREAM *stream) + + Opens an output stream. + + Streams allow for device-to-device + and module-to-module communication, + using an interface somewhat similar + to BSD sockets. + However, the actual implementation depends on + which stream type has been selected + from the deployment manifest. + + :param h: Client object pointer. + :param name: Null-terminated string with the stream name. + This must match the name of one + of the streams defined on the deployment manifest. + :param stream: *[OUT]* + On success, it shall be assigned to a non-negative integer. + Otherwise, it shall be assigned to a negative integer. + + :returns: + + - :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + - :c:enumerator:`~EVP_RESULT.EVP_INVAL` + if the stream was not defined by the + deployment manifest or the stream was not defined for output. + - :c:enumerator:`~EVP_RESULT.EVP_EXIST` + if a stream with the same :c:var:`name` has already been opened. + - :c:enumerator:`~EVP_RESULT.EVP_NOMEM` + if memory could not be allocated. + - :c:enumerator:`~EVP_RESULT.EVP_ERROR` + if an unexpected error occurred. + +Streams +======= + +.. c:function:: EVP_RESULT EVP_streamInputOpen(struct EVP_client *h, const char *name, EVP_STREAM_READ_CALLBACK cb, void *userData, EVP_STREAM *stream) + + Opens an input stream. + + Streams allow for device-to-device + and module-to-module communication, + using an interface somewhat similar + to BSD sockets. + However, the actual implementation depends on + which stream type has been selected + from the deployment manifest. + + :param h: Client object pointer. + :param name: Null-terminated string with the stream name. + This must match the name of one + of the streams defined on the deployment manifest. + :param cb: User callback + that shall be executed + when input data becomes available. + :param userData: Opaque pointer to user-defined data that shall + be passed to :c:var:`cb`. + :param stream: *[OUT]* + On success, it shall be asssigned to a non-negative integer. + Otherwise, it shall be assigned to a negative integer. + + :returns: + + - :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + - :c:enumerator:`~EVP_RESULT.EVP_INVAL` + if the stream was not defined by the + deployment manifest or the stream was not defined for input. + - :c:enumerator:`~EVP_RESULT.EVP_EXIST` + if a stream with the same :c:var:`name` has already been opened. + - :c:enumerator:`~EVP_RESULT.EVP_NOMEM` + if memory could not be allocated. + - :c:enumerator:`~EVP_RESULT.EVP_ERROR` + if an unexpected error occurred. + +.. c:function:: EVP_RESULT EVP_streamClose(struct EVP_client *h, EVP_STREAM stream) + + Closes a stream previously opened with + :c:func:`EVP_streamInputOpen` or + :c:func:`EVP_streamOutputOpen`. + + :param h: Client object pointer. + :param stream: Stream identifier. + + :returns: + + - :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + - :c:enumerator:`~EVP_RESULT.EVP_INVAL` + if the stream was not defined by the deployment manifest. + - :c:enumerator:`~EVP_RESULT.EVP_ERROR` + if an unexpected error occurred. + +.. c:function:: EVP_RESULT EVP_streamWrite(struct EVP_client *h, EVP_STREAM stream, const void *buf, size_t n) + + Sends a buffer over a stream + previously opened with + :c:func:`EVP_streamInputOpen` or + :c:func:`EVP_streamOutputOpen`. + + :param h: Client object pointer. + :param stream: Stream identifier. + :param buf: Buffer to send. + :param n: Buffer length. + + :returns: + + - :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + - :c:enumerator:`~EVP_RESULT.EVP_INVAL` + if the stream was not defined by the + deployment manifest or was not configured for output. + - :c:enumerator:`~EVP_RESULT.EVP_ERROR` + if an unexpected error occurred. diff --git a/docs/interfaces/application_sdk/blob.rst b/docs/interfaces/application_sdk/blob.rst new file mode 100644 index 00000000..96ecb49c --- /dev/null +++ b/docs/interfaces/application_sdk/blob.rst @@ -0,0 +1,532 @@ +.. SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +.. +.. SPDX-License-Identifier: Apache-2.0 + +Blob +#### + +Types +***** + +Enumerates +========== + +.. c:type:: EVP_BLOB_TYPE + + An integer constant for specifying the type of storage service. + + :values: + + .. c:enumerator:: EVP_BLOB_TYPE_AZURE_BLOB + + :value: 0 + + A blob stored in an Azure storage container. + + .. c:enumerator:: EVP_BLOB_TYPE_EVP + + :value: 1 + + [deprecated] A blob stored in the EVP storage provider. + EVP_BLOB_TYPE_EVP_EXT can be used instead of this type. + + .. c:enumerator:: EVP_BLOB_TYPE_HTTP + + :value: 2 + + A blob provided by an ordinary HTTP server. + Only EVP_BLOB_OP_GET operation is supported. + + .. c:enumerator:: EVP_BLOB_TYPE_EVP_EXT + + :value: 3 + + A blob stored in the EVP storage provider. + User can select the storage based on data type. + + .. c:enumerator:: EVP_BLOB_TYPE_HTTP_EXT + + :value: 4 + + A blob provided by an ordinary HTTP server. + Only EVP_BLOB_OP_GET operation is supported. + Allows to pass extra headers for the HTTP + request. + +.. c:type:: EVP_BLOB_OPERATION + + An integer constant for specifying the blob operation. + + :values: + + .. c:enumerator:: EVP_BLOB_OP_GET + + :value: 0 + + Operation GET a blob from the storage service. + + .. c:enumerator:: EVP_BLOB_OP_PUT + + :value: 1 + + Operation PUT a blob into the storage service. + +.. c:type:: EVP_BLOB_IO_RESULT + + The type to represent an outcome of a blob IO callback. + + :values: + + .. c:enumerator:: EVP_BLOB_IO_RESULT_SUCCESS + + :value: 0 + + The operation completed successfully. + + .. c:enumerator:: EVP_BLOB_IO_RESULT_ERROR + + :value: 1 + + The operation failed. + +.. c:type:: EVP_BLOB_RESULT + + The type to represent an outcome of a blob operation. + + :values: + + .. c:enumerator:: EVP_BLOB_RESULT_SUCCESS + + :value: 0 + + The operation completed successfully. + + .. c:enumerator:: EVP_BLOB_RESULT_ERROR + + :value: 1 + + The operation failed. + + .. c:enumerator:: EVP_BLOB_RESULT_ERROR_HTTP + + :value: 2 + + The operation failed with a valid HTTP status. + +.. c:type:: EVP_BLOB_CALLBACK_REASON + + The type to represent the reason of the callback invocation. + + :values: + + .. c:enumerator:: EVP_BLOB_CALLBACK_REASON_DONE + + :value: 0 + + I/O completion, either success or error. + + .. c:enumerator:: EVP_BLOB_CALLBACK_REASON_EXIT + + :value: 1 + + Cancelled or rejected because the requesting Module Instance is + going to exit. + Users must not send any more requests to the agent when this code is + received, and instead users must call \ref EVP_processEvent until + all events are flushed. + + .. c:enumerator:: EVP_BLOB_CALLBACK_REASON_DENIED + + :value: 2 + + A request was denied for transmission. This means the agent could + not enqueue the request due to a full queue. + +Structures +========== + +.. c:struct:: EVP_BlobLocalStore + + A blob operation local store: file or memory + + .. c:member:: const char *filename + + An absolute path of a local file to operate on. + There are restrictions on the filename: + + - It should be in the workspace directory + for the module instance + with type :c:enumerator:`~EVP_BLOB_TYPE.EVP_WORKSPACE_TYPE_DEFAULT`. + - It shouldn't contain parent directory + references. (``..``) + - It shouldn't involve symbolic links. + - It shouldn't end with a slash. + - It shouldn't contain redundant consecutive slashes. + (E.g. ``//path///like////this``) + + .. c:member:: EVP_BLOB_IO_CALLBACK io_cb + + Callback to process partial IO data. + + .. warning:: + + This functionality is provided as a solution for a particular + use case. + + .. warning:: + + Right now, this functionality is available only for NuttX. + + This field is ignored if `filename` is not NULL. + + The callback is invoked for each chunk in the blob. + The chunk sizes are decided by the SDK automatically. + The callback should not assume any specific sizes. + + The callback is called sequentionally from the start of the blob + (smaller offset) to the end of the blob. + If a callback needs to know the current offset in the blob, + the callback should keep track of it by itself, probably using + `userData`. + + .. warning:: + + The callback should return as soon as possible because + otherwise it would interfere the entire device, not only the + calling module instance. + It's recommended for the callback to copy the data to some + application specific buffer and return without any extra + processing. + + .. c:member:: size_t blob_len + + The length of the blob to upload + This field is only used when all conditions below are satisfied: + + - filename is NULL + - PUT operations (type = EVP_BLOB_OP_PUT) + +Azure blobs +----------- + +.. c:struct:: EVP_BlobRequestAzureBlob + + A blob operation request for Azure Blob Storage. + + .. c:member:: const char *url + + Shared Access Signature URL for the blob. + + - :c:enumerator:`~EVP_BLOB_OP.EVP_BLOB_OP_GET` + requires `Read (r)` permission. + - :c:enumerator:`~EVP_BLOB_OP.EVP_BLOB_OP_PUT` + requires `Create (c)` and/or `Write (w)` permission. + + See `Create Storage Service`_. + +.. c:struct:: EVP_BlobResultAzureBlob + + A blob operation result for Azure Blob Storage. + + .. c:member:: EVP_BLOB_RESULT result + + The result of the blob operation. + + .. c:member:: unsigned int http_status + + An HTTP status code. + + .. c:member:: int error + + An errno value. + Only valid for :c:enumerator:`~EVP_BLOB_RESULT.EVP_BLOB_RESULT_ERROR`. + +EVP blobs +--------- + +.. c:struct:: EVP_BlobRequestEvp + + .. deprecated:: 1.0.0 + + A blob operation request for EVP Storage Provider. + + .. c:member:: const char *remote_name + + The unique string to identify this blob. + + Consult the documentation of the EVP Storage Provider + how this string is actually used. + +.. c:struct:: EVP_BlobRequestEvpExt + + A blob operation request for EVP Storage Provider. + + .. c:member:: const char *remote_name + + The unique string to identify file name to upload. + + Consult the documentation of the EVP Storage Provider + how this string is actually used. + + .. c:member:: const char *storage_name + + The unique string to identify + the blob storage based on data type. + + This parameter must be :c:var:`NULL` + to use the default STP or the same string + as configured in EVP Hub + when user create storage. + + When this parameter is :c:var:`NULL`, + a file will be uploaded + to the default EVP storage. + This will be same behavior as + :c:enumerator:`~EVP_BLOB_TYPE.EVP_BLOB_TYPE_EVP`. + + Consult the documentation of the EVP Storage Provider + how this string is actually used. + + .. note:: + + This member corresponds to the :c:var:`key` field of the target STP + configured in the Cloud API. + + +.. c:struct:: EVP_BlobResultEvp + + A blob operation result for EVP Storage Provider. + + .. c:member:: EVP_BLOB_RESULT result + + The result of the blob operation. + + .. c:member:: unsigned int http_status + + An HTTP status code. + + .. c:member:: int error + + An errno value. + Only valid for + :c:enumerator:`~EVP_BLOB_RESULT.EVP_BLOB_RESULT_ERROR`. + +HTTP blobs +---------- + +.. c:struct:: EVP_BlobRequestHttp + + A blob operation request for ordinary HTTP server. + + .. c:member:: const char *url + + URL for the blob. + +.. c:struct:: EVP_BlobResultHttp + + A blob operation result for HTTP server. + + .. c:member:: EVP_BLOB_RESULT result + + The result of the blob operation. + + .. c:member:: unsigned int http_status + + An HTTP status code. + + .. c:member:: int error + + An errno value. + Only valid for + :c:enumerator:`~EVP_BLOB_RESULT.EVP_BLOB_RESULT_ERROR`. + + +HTTP Extended blobs +------------------- + + + +.. c:struct:: EVP_BlobRequestHttpExt + + A blob operation request for ordinary HTTP server, supporting extra + headers. + + +.. c:struct:: EVP_BlobResultHttpExt + + A blob operation result for HTTP server. + + .. c:member:: EVP_BLOB_RESULT result + + The result of the blob operation. + + .. c:member:: unsigned int http_status + + An HTTP status code. + + .. c:member:: int error + + An errno value. + Only valid for + :c:enumerator:`~EVP_BLOB_RESULT.EVP_BLOB_RESULT_ERROR`. + + +Callbacks +========= + +.. c:type:: EVP_BLOB_IO_RESULT (*EVP_BLOB_IO_CALLBACK)(void *buf, size_t buflen, void *userData) + + Function prototype for the callback passed to + :c:struct:`EVP_BlobLocalStore` + + **parameters**: + + - **buf** - The buffer with the contents. + - **buflen** - The length of the buffer. + - **userData** - The userData value specified for :c:func:`EVP_blobOperation`. + + +.. c:type:: void (*EVP_BLOB_CALLBACK)(EVP_BLOB_CALLBACK_REASON reason, const void *result, void *userData) + + Function prototype for the callback passed to the function + :c:func:`EVP_blobOperation`. + + **parameters**: + + - **reason** - One of :c:enum:`EVP_BLOB_CALLBACK_REASON` values. + - **result** - The result of the operation. + Valid only when :c:var:`reason` is :c:enumerator:`~EVP_BLOB_CALLBACK_REASON.EVP_BLOB_CALLBACK_REASON_DONE`. + The type of the :c:var:`result` depends on the + request's :c:var:`type` and :c:var:`op`. + + It is a pointer to: + + - :c:struct:`EVP_BlobResultAzureBlob` for + :c:enumerator:`~EVP_BLOB_TYPE.EVP_BLOB_TYPE_AZURE_BLOB`. + - :c:struct:`EVP_BlobResultEvp` for + :c:enumerator:`~EVP_BLOB_TYPE.EVP_BLOB_TYPE_EVP`. + - :c:struct:`EVP_BlobResultEvp` for + :c:enumerator:`~EVP_BLOB_TYPE.EVP_BLOB_TYPE_EVP_EXT`. + - **userData** - The userData value specified for :c:func:`EVP_blobOperation`. + +Functions +********* + +.. c:function:: EVP_RESULT EVP_blobOperation(struct EVP_client *h, EVP_BLOB_TYPE type, EVP_BLOB_OPERATION op, const void *request, struct EVP_BlobLocalStore *localStore, EVP_BLOB_CALLBACK cb, void *userData) + + Schedule a blob operation + + Enqueues the specified operation :c:var:`op` on a blob of the given :c:var:`type` + which is described by :c:var:`request`, linking it to the given data specified + by :c:var:`localStore` + + :param h: Client object pointer. + :param type: Blob type + :param op: Whether to GET or PUT the blob. + :param request: A pointer to a structure to specify request parameters. + + It is a pointer to: + + - :c:struct:`EVP_BlobRequestAzureBlob` for + :c:enumerator:`~EVP_BLOB_TYPE.EVP_BLOB_TYPE_AZURE_BLOB` + - :c:struct:`EVP_BlobRequestEvp` for + :c:enumerator:`~EVP_BLOB_TYPE.EVP_BLOB_TYPE_EVP` + - :c:struct:`EVP_BlobRequestEvpExt` for + :c:enumerator:`~EVP_BLOB_TYPE.EVP_BLOB_TYPE_EVP_EXT` + - :c:struct:`EVP_BlobRequestHttp` for + :c:enumerator:`~EVP_BLOB_TYPE.EVP_BLOB_TYPE_HTTP` + - :c:struct:`EVP_BlobRequestHttpExt` for + :c:enumerator:`~EVP_BLOB_TYPE.EVP_BLOB_TYPE_HTTP_EXT` + :param localStore: The info about the local store for the data. + The pointed info is copied as needed, so it is + responsibility of the caller to free it. + :param cb: The callback function. It can not be :c:var:`NULL`. + :param userData: The SDK passes this value to the callback as it is. + The SDK doesn't care if it's a valid pointer. + + :returns: :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + +.. c:function:: EVP_RESULT EVP_blobGetUploadURL(struct EVP_client *h, const charstorageName, const charremoteName, EVP_BLOB_CALLBACK cb, void *userData) + + Get the upload URL + This API is only available from native. + It cannot be used from the WASM module. + + .. warning:: + + This is an experimental option and will be + removed in future releases. + + :param h: struct EVP_client. + :param storageName: The unique string to identify the blob storage based + on data type. + :param remoteName: The unique string to identify file name to upload. + Set "" to get container UploadURL. + Set other than "" to get Blob UploadURL. + + :param cb: The callback function. It can not be NULL. + :param userData: The SDK passes this value to the callback as it is. + The SDK doesn't care if it's a valid pointer. + + :returns: :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + +HTTP Extended +============= + +.. c:function:: struct EVP_BlobRequestHttpExt *EVP_BlobRequestHttpExt_initialize(void) + + Initializes an :c:struct:`EVP_BlobRequestHttpExt` + + This function must be called when instantiating an :c:struct:`EVP_BlobRequestHttpExt`. + It returns a pointer to a new request that must be later freed using + :c:func:`EVP_BlobRequestHttpExt_free` + + :returns: Pointer to a newly allocated request struct. :c:var:`NULL` on failure. + +.. c:function:: void EVP_BlobRequestHttpExt_free(struct EVP_BlobRequestHttpExt *request) + + Frees an :c:struct:`EVP_BlobRequestHttpExt` + + This function must be called when freeing an :c:struct:`EVP_BlobRequestHttpExt` + + :param request: A pointer to a :c:struct:`EVP_BlobRequestHttpExt` structure. + +.. c:function:: EVP_RESULT EVP_BlobRequestHttpExt_addHeader(struct EVP_BlobRequestHttpExt *request, const char *name, const char *value) + + Inserts an extra header to :c:struct:`EVP_BlobRequestHttpExt` + + This helper function inserts an extra header into the request. + + :param request: A pointer to a :c:struct:`EVP_BlobRequestHttpExt` structure. + :param name: A pointer to a null-terminated string containing the + name of the header. + :param value: A pointer to a null-terminated string containing the value + of the header. + + :returns: :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + +.. c:function:: EVP_RESULT EVP_BlobRequestHttpExt_addAzureHeader(struct EVP_BlobRequestHttpExt *request) + + Inserts an extra header to :c:struct:`EVP_BlobRequestHttpExt` + + This helper function inserts the azure specific headers in the request. + + :param request: A pointer to a :c:struct:`EVP_BlobRequestHttpExt` structure. + + :returns: :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + +.. c:function:: EVP_RESULT EVP_BlobRequestHttpExt_setUrl(struct EVP_BlobRequestHttpExt *request, char *url) + + Sets the url of :c:struct:`EVP_BlobRequestHttpExt` + + This function sets the url of the request. + + :param request: A pointer to a :c:struct:`EVP_BlobRequestHttpExt` structure. + :param url: The destination URL of the request. + + :returns: :c:enumerator:`~EVP_RESULT.EVP_OK` Success. + + +------- + +.. _Create Storage Service: https://docs.microsoft.com/en-us/rest/api/storageservices/create-service-sas \ No newline at end of file diff --git a/docs/interfaces/application_sdk/experimental.rst b/docs/interfaces/application_sdk/experimental.rst index 327be5af..972c51bc 100644 --- a/docs/interfaces/application_sdk/experimental.rst +++ b/docs/interfaces/application_sdk/experimental.rst @@ -38,7 +38,7 @@ provides the semantics required by its public interface, described below: Where: * - ``EVP_streamInputOpen`` sets up a stream that must be configured with direction + :c:func:`EVP_streamInputOpen` sets up a stream that must be configured with direction ``in`` and name ``name`` from the ``deploymentManifest``. ``cb`` refers to a user-defined callback that will be triggered by the implementation as soon as input data is available. ``user`` is an opaque pointer that is passed to the @@ -47,27 +47,27 @@ Where: pointer. * - ``EVP_streamOutputOpen`` sets up a stream that must be configured with + :c:func:`EVP_streamOutputOpen` sets up a stream that must be configured with direction ``out`` and name ``name`` from the ``deploymentManifest``. * - ``EVP_streamClose`` releases the resources allocated by a stream opened - with ``EVP_streamInputOpen`` or ``EVP_streamOutputOpen``. For streams opened with - ``EVP_streamOutputOpen``\ , ``EVP_streamClose`` shall flush any pending outgoing + :c:func:`EVP_streamClose` releases the resources allocated by a stream opened + with :c:func:`EVP_streamInputOpen` or :c:func:`EVP_streamOutputOpen`. For streams opened with + :c:func:`EVP_streamOutputOpen`\ , :c:func:`EVP_streamClose` shall flush any pending outgoing messages before closing the stream. * - ``EVP_streamWrite`` must queue the request defined by the ``const void *``\ , + :c:func:`EVP_streamWrite` must queue the request defined by the ``const void *``\ , which is the user payload, and the ``size_t``\ , which defines its size. This function must return immediately, and therefore is not required to send data over the network. This should be done asynchronously, for example, via a separate thread. This function can only be used with streams previously opened with - ``EVP_streamOutputOpen``. + :c:func:`EVP_streamOutputOpen`. Another significant difference between POSIX sockets and EVP streams is their direction: while POSIX sockets can be bidirectional, EVP streams are *only* unidirectional. In other words, EVP streams can be either ``in`` or -``out``\ , but never both. As a consequence, using ``EVP_streamWrite`` on an +``out``\ , but never both. As a consequence, using :c:func:`EVP_streamWrite` on an ``in`` stream will return an error. Bidirectional streams are currently not planned, but it should still be @@ -116,15 +116,9 @@ might as well not exist if the stream type does not require it. The following stream types are supported: -* ``nng``\ : based on the `nng`_ library. In - the case of an agent using a local SDK implementation, ``nng`` streams are - only available if ``EVP_AGENT_LOCAL_SDK_NNG_STREAMS`` is defined. Moreover, - ``nng`` are known to have issues on NuttX + ESP32; issues that have not been - investigated. * ``null``\ : a placeholder implementation only meant for testing purposes. ``null`` streams are always supported by the agent. -* ``posix``\ : only uses the POSIX C standard library, which makes it a more - lightweight and convenient choice, compared to ``nng`` streams. +* ``posix``\ : only uses the POSIX C standard library. Take into account that, if a module does not use any stream, the ``streams`` object must not exist. @@ -133,7 +127,7 @@ Open the stream from the module instance ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When a module instance has been started with a set of configured streams, a -call to ``EVP_streamInputOpen`` or ``EVP_streamOutputOpen`` will look up the +call to :c:func:`EVP_streamInputOpen` or :c:func:`EVP_streamOutputOpen` will look up the current ``deploymentManifest`` to check whether the stream was defined accordingly. @@ -157,14 +151,14 @@ The example module below shows how to open an output stream called } If ``my-stream`` could not be found on the ``streams`` JSON object belonging to -the calling module instance, ``EVP_INVAL`` will be returned. See the -documentation for ``EVP_streamInputOpen`` and ``EVP_streamOutputOpen`` for a list of possible error values. +the calling module instance, :c:enumerator:`~EVP_RESULT.EVP_INVAL` will be returned. See the +documentation for :c:func:`EVP_streamInputOpen` and :c:func:`EVP_streamOutputOpen` for a list of possible error values. Once a stream has been opened successfully: * Input streams shall get their user-defined callback triggered once input data is available. -* Output streams can call ``EVP_streamWrite``. +* Output streams can call :c:func:`EVP_streamWrite`. High-level design ----------------- @@ -199,7 +193,6 @@ However, this implementation must be complemented with: * Stream type-specific implementation: - * `nng.c `_. * `null.c `_. * `posix.c `_. @@ -251,7 +244,7 @@ where: * ``init`` performs the required type-specific initialization of a stream. The desired stream configuration is contained inside the ``cfg`` member on the ``struct stream_impl`` passed to this function. A status code as defined - by ``EVP_RESULT`` must be returned. If not ``EVP_OK``\ , the status code shall be + by :c:enum:`~EVP_RESULT` must be returned. If not ``EVP_OK``\ , the status code shall be propagated to the user. * ``close`` must deallocate any resources previously allocated by a call to ``init``. Returns zero if successful, non-zero otherwise. @@ -269,9 +262,6 @@ where: standard ``atexit(3)`` function. It can be a null pointer if no actions are required. - * Note: ``atexit`` was required by ``nng`` streams so as to avoid a false - positive from ``valgrind(1)`` when closing the agent. - Input streams ------------- @@ -336,7 +326,7 @@ how the event should be stored in the event queue. Local SDK ^^^^^^^^^ -Since ``EVP_client`` was already designed to be accessed from multiple threads +Since :c:struct:`EVP_client` was already designed to be accessed from multiple threads in the case of local SDK, the implementation for ``stream_insert_read_event`` was relatively straightforward: the ``struct sdk_event_stream_read_available`` instance can be safely appended into the queue as long as the ``sdk_{un}lock`` @@ -406,7 +396,7 @@ are never meant to be available to users in any case. As a consequence of this, ``process_stream_in`` has no way to retrieve the ``struct EVP_client`` related to the stream, since its caller is only limited -to a ``struct sdk_client`` instance. This forces ``EVP_initialize`` to set up +to a ``struct sdk_client`` instance. This forces :c:func:`EVP_initialize` to set up a callback/opaque-pointer pair that allows `sdk.c`_ to insert the new event into ``struct EVP_client`` member ``events``, which must be assigned to its ``struct sdk_transport`` instance, which is the only data @@ -447,7 +437,6 @@ users. -------- -.. _nng: https://github.com/nanomsg/nng .. _streams: https://github.com/SonySemiconductorSolutions/edge-virtualization-platform/tree/main/src/libevp-agent/stream .. _stream.c: https://github.com/SonySemiconductorSolutions/edge-virtualization-platform/tree/main/src/libevp-agent/stream/stream.c .. _stream.h: https://github.com/SonySemiconductorSolutions/edge-virtualization-platform/tree/main/src/libevp-agent/stream/stream.h diff --git a/docs/interfaces/application_sdk/features.rst b/docs/interfaces/application_sdk/features.rst index acd47e79..3d63eb39 100644 --- a/docs/interfaces/application_sdk/features.rst +++ b/docs/interfaces/application_sdk/features.rst @@ -9,7 +9,7 @@ Most of the features described below are available to module instances via the use of an opaque handle. In the C EVP Application SDK, -``struct EVP_client`` is the opaque pointer type +:c:struct:`EVP_client` is the opaque pointer type exposed to users. In the Python EVP SDK, the ``evp.client`` module @@ -38,11 +38,7 @@ whenever a given configuration topic is received. In the C EVP Application SDK, module instances can subscribe to a given configuration -via the ``EVP_setConfigurationCallback`` function: - -.. code:: C - - EVP_RESULT EVP_setConfigurationCallback(struct EVP_client *h, EVP_CONFIGURATION_CALLBACK cb, void *userData); +via the :c:func:`EVP_setConfigurationCallback` function. In the Python EVP SDK, module instances can subscribe @@ -86,11 +82,7 @@ by the EVP Agent. In the C EVP SDK, states can be sent -using the ``EVP_sendState`` function: - -.. code:: C - - EVP_RESULT EVP_sendState(struct EVP_client *h, const char *topic, const void *state, size_t statelen, EVP_STATE_CALLBACK cb, void *userData); +using the :c:func:`EVP_sendState` function. In the Python EVP SDK, the ``evp.state`` module @@ -115,7 +107,7 @@ using the ``State.send`` method: The ``State.send`` method shall raise an exception -if the underlying call to ``EVP_sendState`` fails. +if the underlying call to :c:func:`EVP_sendState` fails. Telemetries =========== @@ -136,11 +128,7 @@ where all telemetries for each module instance are defined. blob operations should be used instead. In the C EVP SDK, telemetries can be sent -using the ``EVP_sendTelemetry`` function: - -.. code:: C - - EVP_RESULT EVP_sendTelemetry(struct EVP_client *h, const struct EVP_telemetry_entry *entries, size_t nentries, EVP_TELEMETRY_CALLBACK cb, void *userData); +using the :c:func:`EVP_sendTelemetry` function. Where ``entries`` refers to an arbitrary number of telemetry entries, @@ -150,7 +138,7 @@ is defined by the ``nentries`` parameter. .. note:: - Since ``EVP_sendTelemetry`` takes + Since :c:func:`EVP_sendTelemetry` takes a read-only pointer to such entries, it is advisable that the user-defined callback pointed to by ``user`` @@ -207,29 +195,17 @@ which are both defined as strings. In the C EVP SDK, a module can subscribe to module direct command requests -via the ``EVP_setRpcCallback`` function: - -.. code:: C - - EVP_RESULT EVP_setRpcCallback(struct EVP_client *h, EVP_RPC_REQUEST_CALLBACK cb, void *userData); +via the :c:func:`EVP_setRpcCallback` function. All module direct commands are then mapped to a single, user-defined callback -with the following signature: - -.. code:: C - - typedef void (*EVP_RPC_REQUEST_CALLBACK)(EVP_RPC_ID id, const char *methodName, const char *params, void *userData); +with the :c:type:`EVP_RPC_REQUEST_CALLBACK` signature. ``id`` is an opaque identifier dedicated to match a request against a response, which is passed -via the ``EVP_sendRpcResponse``: - -.. code:: C - - EVP_RESULT EVP_sendRpcResponse(struct EVP_client *h, EVP_RPC_ID id, const char *response, EVP_RPC_RESPONSE_STATUS status, EVP_RPC_RESPONSE_CALLBACK cb, void *userData); +via the :c:func:`EVP_sendRpcResponse`. In the Python EVP SDK, modules can subscribe @@ -274,11 +250,7 @@ using a variety of protocols. In the C EVP SDK, all these operations are performed -by the :c:func:`EVP_blobOperation` function: - -.. code:: C - - EVP_RESULT EVP_blobOperation(struct EVP_client *h, EVP_BLOB_TYPE type, EVP_BLOB_OPERATION op, const void *request, struct EVP_BlobLocalStore *localStore, EVP_BLOB_CALLBACK cb, void *userData); +by the :c:func:`EVP_blobOperation` function. Every blob operation consumes a user-defined callback that will be executed by the agent diff --git a/docs/interfaces/application_sdk/index.rst b/docs/interfaces/application_sdk/index.rst index e2130265..0e8899a5 100644 --- a/docs/interfaces/application_sdk/index.rst +++ b/docs/interfaces/application_sdk/index.rst @@ -19,3 +19,6 @@ for building EVP applications. features usage experimental + base + blob + \ No newline at end of file diff --git a/docs/interfaces/application_sdk/usage.rst b/docs/interfaces/application_sdk/usage.rst index 68fa5fa9..b34e73ce 100644 --- a/docs/interfaces/application_sdk/usage.rst +++ b/docs/interfaces/application_sdk/usage.rst @@ -17,32 +17,32 @@ if the module did not exit gracefully the agent will forcefully stop and kill the module. This is implemented within the module instance “supervisor”. -All events in a module instance are processed by ``EVP_processEvent``. +All events in a module instance are processed by :c:func:`EVP_processEvent`. If the agent wants the module instance to exit, -``EVP_processEvent`` would still dispatch any pending events. +:c:func:`EVP_processEvent` would still dispatch any pending events. The agent would then notify the module via the event callback when an event is generated by: -- ``EVP_sendState`` would have ``EVP_STATE_CALLBACK_REASON_EXIT`` +- :c:func:`EVP_sendState` would have :c:enumerator:`~EVP_STATE_CALLBACK_REASON.EVP_STATE_CALLBACK_REASON_EXIT` as its ``reason`` on the event callback. -- ``EVP_sendTelemetry`` would have ``EVP_TELEMETRY_CALLBACK_REASON_EXIT`` +- :c:func:`EVP_sendTelemetry` would have :c:enumerator:`~EVP_TELEMETRY_CALLBACK_REASON.EVP_TELEMETRY_CALLBACK_REASON_EXIT` as its ``reason`` on the event callback. -- ``EVP_sendMessage`` would have ``EVP_MESSAGE_SENT_CALLBACK_REASON_EXIT`` +- :c:func:`EVP_sendMessage` would have :c:enumerator:`~EVP_MESSAGE_SENT_CALLBACK_REASON.EVP_MESSAGE_SENT_CALLBACK_REASON_EXIT` as its ``reason`` on the event callback. -- ``EVP_sendRpcResponse`` would have ``EVP_RPC_RESPONSE_CALLBACK_REASON_EXIT`` +- :c:func:`EVP_sendRpcResponse` would have :c:enumerator:`~EVP_RPC_RESPONSE_CALLBACK_REASON.EVP_RPC_RESPONSE_CALLBACK_REASON_EXIT` as its ``reason`` on the event callback. -- ``EVP_blobOperation`` would have ``EVP_BLOB_CALLBACK_REASON_EXIT`` +- :c:func:`EVP_blobOperation` would have :c:enumerator:`~EVP_BLOB_CALLBACK_REASON.EVP_BLOB_CALLBACK_REASON_EXIT` as its ``reason`` on the event callback. -``EVP_processEvent`` would still return ``EVP_SHOULD_EXIT`` +:c:func:`EVP_processEvent` would still return ``EVP_SHOULD_EXIT`` only if there are no more events pending on the input queue to the module. When any of the ``*_REASON_EXIT`` error codes is received, the module instance must stop generating any new events, -and keep calling ``EVP_processEvent`` until ``EVP_SHOULD_EXIT`` is returned. +and keep calling :c:func:`EVP_processEvent` until ``EVP_SHOULD_EXIT`` is returned. This is done for the module to be able to process all the pending events before it actually exits. Some examples of functions that generate events are -``EVP_sendState``, ``EVP_sendTelemetry`` and ``EVP_sendMessage``. +:c:func:`EVP_sendState`, :c:func:`EVP_sendTelemetry` and :c:func:`EVP_sendMessage`. Sample module ------------- @@ -89,10 +89,10 @@ A correct implementation of the module would be } When the module instance is requested to stop, -``EVP_TELEMETRY_CALLBACK_REASON_EXIT`` is signalled by ``telemetry_cb``, -so that the module instance does not call ``EVP_sendTelemetry`` anymore. +:c:enumerator:`~EVP_TELEMETRY_CALLBACK_REASON.EVP_TELEMETRY_CALLBACK_REASON_EXIT` is signalled by ``telemetry_cb``, +so that the module instance does not call :c:func:`EVP_sendTelemetry` anymore. Then, the module instance flushes all the events in the queue, -until ``EVP_processEvent`` returns ``EVP_SHOULD_EXIT``, +until :c:func:`EVP_processEvent` returns ``EVP_SHOULD_EXIT``, so the module instance ``break``s and finally ``return``s from ``main``. diff --git a/docs/license.rst b/docs/license.rst index c7621967..577ca318 100644 --- a/docs/license.rst +++ b/docs/license.rst @@ -40,12 +40,6 @@ MQTT-C Copyright (c) 2018 Liam Bindle -nng ---- - -Copyright 2021 Staysail Systems, Inc. -Copyright 2018 Capitar IT Group BV - BSD-3-Clause License ******************** diff --git a/docs/requirements.txt b/docs/requirements.txt index 2e7434dc..418c2e1a 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -6,3 +6,4 @@ sphinx==7.1.2 sphinx-rtd-theme==1.3.0rc1 myst_parser==3.0.0 rstcheck==6.2.4 +sphinx-copybutton==0.5.2 diff --git a/docs/testing/index.rst b/docs/testing/index.rst index 5766d6aa..a33130ef 100644 --- a/docs/testing/index.rst +++ b/docs/testing/index.rst @@ -293,7 +293,6 @@ The full list of checks enabled is: fsanitize=shift fsanitize=undefined fsanitize=unreachable - fsanitize=unsigned-integer-overflow fsanitize=vla-bound More information about every specific option can be found in the diff --git a/include/evp_mbedtls_config.h b/include/evp_mbedtls_config.h index 0b99f7be..b9d2c24b 100644 --- a/include/evp_mbedtls_config.h +++ b/include/evp_mbedtls_config.h @@ -5,3 +5,5 @@ */ #undef MBEDTLS_DEBUG_C +#define MBEDTLS_THREADING_C +#define MBEDTLS_THREADING_PTHREAD diff --git a/scripts/build/sys/posix.mk b/scripts/build/sys/posix.mk index ee16b94d..0c166723 100644 --- a/scripts/build/sys/posix.mk +++ b/scripts/build/sys/posix.mk @@ -5,3 +5,4 @@ SYS_CFLAGS = -pthread -DMBEDTLS_USER_CONFIG_FILE="" SYS_LDFLAGS = -pthread SYS_LDLIBS = -lpthread -lrt -ldl +MBEDTLS_USER_CONFIG_FILE = $(PWD)/$(INCDIR)/evp_mbedtls_config.h diff --git a/scripts/build/tool/clang.mk b/scripts/build/tool/clang.mk index 0b219e32..09eb1f1a 100644 --- a/scripts/build/tool/clang.mk +++ b/scripts/build/tool/clang.mk @@ -25,7 +25,6 @@ SANITIZER_ENABLED=\ -fsanitize=shift\ -fsanitize=undefined\ -fsanitize=unreachable\ - -fsanitize=unsigned-integer-overflow\ -fsanitize=vla-bound\ TOOL_ASFLAGS = -c diff --git a/scripts/cmake-flatcc.sh b/scripts/cmake-flatcc.sh index 87e5c069..39914d01 100755 --- a/scripts/cmake-flatcc.sh +++ b/scripts/cmake-flatcc.sh @@ -24,7 +24,6 @@ cmake \ -DCMAKE_C_COMPILER="${CC:-cc}" \ -DCMAKE_C_FLAGS="${CFLAGS} -DFLATCC_DEBUG_VERIFY=0" \ -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - -DFLATCC_RTONLY=ON \ -DFLATCC_CXX_TEST=OFF \ -DFLATCC_INSTALL=ON \ -DFLATCC_DEBUG_CLANG_SANITIZE=OFF \ diff --git a/scripts/cmake-mbedtls.sh b/scripts/cmake-mbedtls.sh index 2c41cc0e..301b251a 100755 --- a/scripts/cmake-mbedtls.sh +++ b/scripts/cmake-mbedtls.sh @@ -27,6 +27,7 @@ cmake \ -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ -DENABLE_TESTING=OFF \ -DENABLE_PROGRAMS=OFF \ + ${MBEDTLS_USER_CONFIG_FILE:+-DMBEDTLS_USER_CONFIG_FILE="$MBEDTLS_USER_CONFIG_FILE"} \ .. trap "" EXIT INT TERM HUP diff --git a/scripts/formatter-python.sh b/scripts/formatter-python.sh index 2af99b00..0725fd9b 100755 --- a/scripts/formatter-python.sh +++ b/scripts/formatter-python.sh @@ -30,7 +30,6 @@ EXCLUDE_NAMES="${EXCLUDE_NAMES},build" # Exclude submodules files EXCLUDE_NAMES="${EXCLUDE_NAMES},src/flatcc" EXCLUDE_NAMES="${EXCLUDE_NAMES},src/mbedtls" -EXCLUDE_NAMES="${EXCLUDE_NAMES},src/nng" EXCLUDE_NAMES="${EXCLUDE_NAMES},src/nuttx" EXCLUDE_NAMES="${EXCLUDE_NAMES},src/nuttx-apps" EXCLUDE_NAMES="${EXCLUDE_NAMES},src/wasm-micro-runtime" diff --git a/scripts/mk-agent-deb.sh b/scripts/mk-agent-deb.sh index 87cc26fa..216ad666 100755 --- a/scripts/mk-agent-deb.sh +++ b/scripts/mk-agent-deb.sh @@ -52,7 +52,7 @@ Section: contrib/misc Version: $version Priority: optional Architecture: $arch -Maintainer: Midokura +Maintainer: Sony Semiconductor Solutions Depends: libc6 (>= 2.35), ca-certificates Vcs-Browser: https://github.com/SonySemiconductorSolutions/edge-virtualization-platform Vcs-Git: https://github.com/SonySemiconductorSolutions/edge-virtualization-platform @@ -64,8 +64,8 @@ EOF cat > dist/DEBIAN/copyright < +Upstream-Contact: Sony Semiconductor Solutions +Source: Files: * Copyright: 2024 Sony Semiconductor Solutions Corporation diff --git a/scripts/mk-sbom b/scripts/mk-sbom index 070d8d67..7e20388c 100755 --- a/scripts/mk-sbom +++ b/scripts/mk-sbom @@ -127,7 +127,6 @@ apply_exceptions() s@(.*/src/flatcc/[^ ]*).*@\1 APACHE-2.0@ s@(.*/src/wasm-micro-runtime/.*/sandboxed-system-primitives/[^ ]*).*@\1 APACHE-2.0_WITH_LLVM-EXCEPTION@ s@(.*/src/wasm-micro-runtime/core/iwasm/include/wasm_c_api.h).*@\1 APACHE-2.0_WITH_LLVM-EXCEPTION@ - s@(.*/src/nng/[^ ]*).*@\1 MIT@ s@(/usr/include/[^ ]*).*@\1 LPGL-2.1-OR-LATER@ s@(/usr/lib/gcc/[^ ]*).*@\1 LPGL-2.1-OR-LATER@ s@(/usr/lib/linux/[^ ]*).*@\1 GPL-2.0_WITH_LINUX-SYSCALL-NOTE@ diff --git a/scripts/mk-sdk-deb.sh b/scripts/mk-sdk-deb.sh new file mode 100755 index 00000000..a607053e --- /dev/null +++ b/scripts/mk-sdk-deb.sh @@ -0,0 +1,100 @@ +#!/bin/sh + +# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -e + +arch=amd64 +version=0.0.0 + +usage() +{ + echo "usage: mk-sdk-deb [-a arch] [-V version]" >&2 + exit 1 +} + +while test $# -gt 0; do + case "$1" in + -a) + arch=${2?`usage`} + shift 2 + ;; + -V) + version=${2?`usage`} + shift 2 + ;; + *) + usage + ;; + esac +done + +rm -rf dist +trap "rm -rf dist $$.tmp" EXIT HUP INT TERM + +case $arch in +aarch64) + debarch=arm64 + ;; +x86_64) + debarch=amd64 + ;; +esac + +# create deb package +mkdir -p dist/DEBIAN + +cat > dist/DEBIAN/control < +Depends: libc6 (>= 2.35) +Recommends: evp-agent +Vcs-Browser: https://github.com/SonySemiconductorSolutions/edge-virtualization-platform +Vcs-Git: https://github.com/SonySemiconductorSolutions/edge-virtualization-platform +Description: Software Development Kit for EVP applications + This package provides the required interfaces and libraries + to build EVP applications. +EOF + +cat > dist/DEBIAN/copyright < + +Files: * +Copyright: 2024 Sony Semiconductor Solutions Corporation +License: Apache-2.0 + +Files: src/flatcc +Copyright: 2015 Mikkel F. Jørgensen, dvide.com +License: Apache-2.0 + +Files: include/internal/queue.h +Copyright: (c) 1991, 1993 The Regents of the University of California. +License: BSD-3-Clause +EOF + +mkdir -p dist/usr/lib/$arch-linux-gnu +mkdir -p dist/usr/include/evp + +cp lib/libevp-app-sdk.a dist/usr/lib/$arch-linux-gnu/ +cp \ + include/evp/sdk_base.h\ + include/evp/sdk_blob_azure.h\ + include/evp/sdk_blob_evp.h\ + include/evp/sdk_blob.h\ + include/evp/sdk_blob_http_ext.h\ + include/evp/sdk_blob_http.h\ + include/evp/sdk.h\ + include/evp/sdk_sys.h\ + include/evp/sdk_types.h\ + dist/usr/include/evp/ + +dpkg-deb --build dist libevp-app-sdk-dev-${version}_$debarch.deb diff --git a/scripts/mkdeps.sh b/scripts/mkdeps.sh index 0666b0b2..65f39f67 100755 --- a/scripts/mkdeps.sh +++ b/scripts/mkdeps.sh @@ -30,18 +30,6 @@ then git submodule update --init --recursive src/mbedtls fi -# In the NuttX build, NNG is not built by us but is included and built -# by nuttx build system. In those cases, CONFIG_NETUTILS_NNG is selected, -# so we skip our build -if test "$CONFIG_EVP_AGENT_LOCAL_SDK_NNG_STREAMS" = y && - test "$CONFIG_NETUTILS_NNG" != y -then - libs="$libs -lnng" - dirs="$dirs nng" - files="$files \$(LIBDIR)/libnng.a" - git submodule update --init src/nng -fi - # In the NuttX build, WAMR is not built by us but is included and built by # nuttx build system. In those cases, CONFIG_INTERPRETERS_WAMR is selected, # so we skip our build @@ -57,7 +45,7 @@ fi if test "$CONFIG_EVP_SDK_SOCKET" = y then libs="$libs -lflatccrt" - dirs="$dirs flatcc" + dirs="$dirs flatcc sdkenc" files="$files \$(LIBDIR)/libflatccrt.a" git submodule update --init src/flatcc fi diff --git a/scripts/rules.mk b/scripts/rules.mk index 798664f7..cca57f35 100644 --- a/scripts/rules.mk +++ b/scripts/rules.mk @@ -7,7 +7,8 @@ all: # Macros related to the version of the agent -VERSION = 1.42.0 +VERSION = 1.43.0 +SDK_VERSION = 1.0.0 # Default value for configuration macros O = o @@ -31,9 +32,6 @@ LDINCLUDES= -L$(LIBDIR) # Include optional personal preferences -include $(PROJECTDIR)/config.mk -# include kconfig configuration --include $(PROJECTDIR)/.config - # Include configuration definitions include $(SCRIPTDIR)/build/tool/$(TOOL).mk include $(SCRIPTDIR)/build/sys/$(SYS).mk @@ -198,6 +196,7 @@ distclean-dirs: FORCE ARCH=$(ARCH) \ CFLAGS='$(CFLAGS)' \ MBEDTLS_CFLAGS='$(MBEDTLS_CFLAGS)' \ + MBEDTLS_USER_CONFIG_FILE='$(MBEDTLS_USER_CONFIG_FILE)' \ $(SCRIPTDIR)/cmake-$*.sh $(PWD)/$(PROJECTDIR) %: %/build/Makefile FORCE diff --git a/sources.mk b/sources.mk index 95b8c447..1a3a38a8 100644 --- a/sources.mk +++ b/sources.mk @@ -179,7 +179,3 @@ endif ifeq ($(CONFIG_EVP_AGENT_MODULE_IMPL_DOCKER_RAW_CONTAINER_SPEC),y) CSRCS += container_spec.c endif - -ifeq ($(CONFIG_EVP_AGENT_LOCAL_SDK_NNG_STREAMS),y) -CSRCS += stream/nng.c -endif diff --git a/src/Makefile b/src/Makefile index 5c053593..65da3f77 100644 --- a/src/Makefile +++ b/src/Makefile @@ -12,6 +12,7 @@ EVP_LIBS = \ DIRS = \ evp_agent\ libparson\ + sdkenc\ $(EVP_LIBS) include $(PROJECTDIR)/scripts/rules.mk @@ -32,8 +33,9 @@ libevp-agent: libevp-utils evp_agent: libevp-agent libevp-utils +sdkenc: flatcc + # cmake dependencies wasm-micro-runtime: wasm-micro-runtime/build/Makefile flatcc: flatcc/build/Makefile mbedtls: mbedtls/build/Makefile -nng: nng/build/Makefile diff --git a/src/libevp-agent/Kconfig b/src/libevp-agent/Kconfig index edd2e091..5c15fb70 100644 --- a/src/libevp-agent/Kconfig +++ b/src/libevp-agent/Kconfig @@ -36,7 +36,6 @@ config EXTERNALS_EVP_AGENT # * CONFIG_LIBM # * CONFIG_ARCH_MATH_H # * toolchain-provided math.h - # * CONFIG_LIBNEWLIBM (midokura/incubator-nuttx specific) # It's the responsibility of the user to enable one of them. # For JSON number serialization in parson diff --git a/src/libevp-agent/Kconfig.common b/src/libevp-agent/Kconfig.common index 606bb694..fdd16c0e 100644 --- a/src/libevp-agent/Kconfig.common +++ b/src/libevp-agent/Kconfig.common @@ -209,18 +209,6 @@ config EVP_BLOB_GET_UPLOAD_URL ---help--- Retrieve STP access token. -config EVP_AGENT_LOCAL_SDK_NNG_STREAMS - bool "Enables EVP_stream type nng on local SDK builds" - default n - ---help--- - This option allows the use of EVP_streams of type nng when local - SDK is enabled. When not set, calls to EVP_streamInputOpen or - EVP_streamOutputOpen shall return EVP_NOTSUP. This can help reduce - the additional memory footprint required by the nng library. - - Since nng is bundled separately from the agent on remote SDK - builds, this option does not affect builds using remote SDK builds. - config EVP_MODULE_INSTANCE_STOP_TIMEOUT int "Maximum time before force stopping spawed instance after stop request" depends on EVP_MODULE_IMPL_SPAWN diff --git a/src/libevp-agent/Makefile b/src/libevp-agent/Makefile index 2881f23a..e55d1644 100644 --- a/src/libevp-agent/Makefile +++ b/src/libevp-agent/Makefile @@ -5,6 +5,7 @@ PROJECTDIR = ../.. include $(PROJECTDIR)/scripts/rules.mk +-include $(PROJECTDIR)/.config MORE_CPPFLAGS = \ -IMQTT-C/include\ @@ -156,7 +157,6 @@ obj-$(CONFIG_EVP_MODULE_IMPL_OBJ) += module_impl_obj.o obj-$(CONFIG_EVP_MODULE_IMPL_SPAWN) += module_impl_spawn.o module_instance_impl_spawn.o obj-$(CONFIG_EVP_MODULE_IMPL_PYTHON) += module_impl_python.o module_instance_impl_python.o obj-$(CONFIG_EVP_AGENT_MODULE_IMPL_DOCKER_RAW_CONTAINER_SPEC) += container_spec.o -obj-$(CONFIG_EVP_AGENT_LOCAL_SDK_NNG_STREAMS) += stream/nng.o obj-$(CONFIG_EVP_TWINS_PERSISTENCE) += persist.o obj-$(CONFIG_EVP_TWINS_NO_PERSISTANCE) += nopersist.o diff --git a/src/libevp-agent/device_state.h b/src/libevp-agent/device_state.h index 2ecd1187..1be7a449 100644 --- a/src/libevp-agent/device_state.h +++ b/src/libevp-agent/device_state.h @@ -10,8 +10,6 @@ * @brief This function fills a @c JSON_Object with device state data, * as defined by the following JSON schema: * - * https://github.com/midokura/evp-onwire-schema/blob/main/schema/device-state.schema.json - * * @param o JSON object to fill with device state data. * * @return Returns 0 if successful, -1 otherwise. diff --git a/src/libevp-agent/docker.c b/src/libevp-agent/docker.c index ec6fcaaa..07ca8bfe 100644 --- a/src/libevp-agent/docker.c +++ b/src/libevp-agent/docker.c @@ -40,18 +40,16 @@ /* * Labels for docker containers. */ -#define EVP_LABEL_MANAGED "com.midokura.evp.managed-by-evp-agent" +#define EVP_LABEL_MANAGED "com.sss.evp.managed-by-evp-agent" /* - * XXX the filters is hardcoded because I don't want to implement - * url quoting. * - * >>> d={'label':['com.midokura.evp.managed-by-evp-agent']} + * >>> d={'label':['com.sss.evp.managed-by-evp-agent']} * >>> urllib.parse.quote(json.dumps(d)) - * '%7B%22label%22%3A%20%5B%22com.midokura.evp.managed-by-evp-agent%22%5D%7D' + * '%7B%22label%22%3A%20%5B%22com.sss.evp.managed-by-evp-agent%22%5D%7D' */ static const char *evp_label_managed_filters = - "%7B%22label%22%3A%20%5B%22com.midokura.evp.managed-by-evp-agent%22%" + "%7B%22label%22%3A%20%5B%22" EVP_LABEL_MANAGED "%22%" "5D%7D"; struct docker { @@ -417,7 +415,7 @@ docker_get_registry_auth_var_name(const char *fromImage) * for the image "xxx/yyy:zzz", * look at the "EVP_REGISTRY_AUTH_xxx" environment variable. * - * e.g. for the image "ghcr.io/midokura/sdktest:latest", + * e.g. for the image "ghcr.io/aaa/bbb:latest", * use "EVP_REGISTRY_AUTH_ghcr.io". * * REVISIT: maybe it's simpler to reject non-fully-qualified names. diff --git a/src/libevp-agent/evp_agent.c b/src/libevp-agent/evp_agent.c index 1ba9fd21..b1642279 100644 --- a/src/libevp-agent/evp_agent.c +++ b/src/libevp-agent/evp_agent.c @@ -188,6 +188,9 @@ evp_agent_start(struct evp_agent_context *ctxt) /* initialize the https singleton */ https_ssl_config_init(&ctxt->tls_context->https.ssl_conf); + /* initialize state len lock */ + xpthread_mutex_init(&g_evp_global.instance_states_lock); + /* Configure data directory paths */ path_init(getenv("EVP_DATA_DIR")); @@ -357,6 +360,7 @@ evp_agent_stop(struct evp_agent_context *ctxt) module_instance_deinit(); + xpthread_mutex_destroy(&g_evp_global.instance_states_lock); path_free(); deinit_local_twins_db(); module_log_cap_stop(); diff --git a/src/libevp-agent/global.h b/src/libevp-agent/global.h index ff1f791e..9c693b78 100644 --- a/src/libevp-agent/global.h +++ b/src/libevp-agent/global.h @@ -7,6 +7,7 @@ #include #include "path.h" +#include "xpthread.h" struct map; @@ -29,7 +30,8 @@ struct global { JSON_Value *desired; // shared attributes JSON_Value *current; // client attributes (our current state) JSON_Value *instance_states; // Module instance states - + size_t instance_states_len; + struct evp_lock instance_states_lock; /* * Reconcile status */ diff --git a/src/libevp-agent/manifest.c b/src/libevp-agent/manifest.c index b8f69096..165313a6 100644 --- a/src/libevp-agent/manifest.c +++ b/src/libevp-agent/manifest.c @@ -323,133 +323,6 @@ convert_topic_list(JSON_Object *o, struct TopicList **resultp) return ret; } -static int -get_nng_stream_mode(const JSON_Object *o, const struct Stream *stream, - struct StreamNng *snng) -{ - const char *mode = json_object_get_string(o, "mode"); - if (mode == NULL) { - xlog_error("could not find stream mode"); - return -1; - } - - if (!strcmp(mode, "dial")) { - if (stream->direction != STREAM_DIRECTION_OUT) { - xlog_error( - "dial mode can only work with output streams"); - return -1; - } - snng->mode = STREAM_NNG_MODE_DIAL; - } else if (!strcmp(mode, "listen")) { - if (stream->direction != STREAM_DIRECTION_IN) { - xlog_error("listen mode can only work with input " - "streams"); - return -1; - } - snng->mode = STREAM_NNG_MODE_LISTEN; - } else { - xlog_error("invalid stream mode %s", mode); - return -1; - } - - return 0; -} - -static int -get_nng_stream_protocol(const JSON_Object *o, const struct Stream *stream, - struct StreamNng *snng) -{ - const char *protocol = json_object_get_string(o, "protocol"); - if (protocol == NULL) { - xlog_error("could not find stream protocol"); - return EINVAL; - } - - if (!strcmp(protocol, "push")) { - if (stream->direction != STREAM_DIRECTION_OUT) { - xlog_error("push protocol can only work with output " - "streams"); - return EINVAL; - } - snng->protocol = STREAM_NNG_PROTOCOL_PUSH; - } else if (!strcmp(protocol, "pull")) { - if (stream->direction != STREAM_DIRECTION_IN) { - xlog_error("pull protocol can only work with input " - "streams"); - return EINVAL; - } - snng->protocol = STREAM_NNG_PROTOCOL_PULL; - } else { - xlog_error("invalid stream protocol %s", protocol); - return EINVAL; - } - - return 0; -} - -static int -get_nng_stream_connection(const JSON_Object *o, const struct Stream *stream, - struct StreamNng *snng) -{ - const char *connection = - json_object_get_string(o, "connection_string"); - if (connection == NULL) { - xlog_error("could not find stream connection string"); - return EINVAL; - } - - snng->connection = strdup(connection); - if (snng->connection == NULL) { - xlog_error("strdup(3) failed with errno %d", errno); - return ENOMEM; - } - - return 0; -} - -static int -convert_nng_stream(const JSON_Object *o, struct Stream *s) -{ - int ret = EINVAL; - const JSON_Value *v = json_object_get_value(o, "parameters"); - struct StreamNng snng = {0}; - - if (v == NULL) { - xlog_error("unexpected null parameters"); - goto end; - } - - const JSON_Object *nobj = json_value_get_object(v); - if (nobj == NULL) { - xlog_error("unexpected null parameters object"); - goto end; - } - - static int (*const params[])(const JSON_Object *, - const struct Stream *, - struct StreamNng *) = { - get_nng_stream_mode, get_nng_stream_protocol, - get_nng_stream_connection}; - - for (size_t i = 0; i < __arraycount(params); i++) { - ret = params[i](nobj, s, &snng); - if (ret != 0) { - goto end; - } - } - - s->type = STREAM_TYPE_NNG; - s->params.nng = snng; - ret = 0; - -end: - if (ret != 0) { - free(snng.connection); - } - - return ret; -} - static int get_posix_stream_hostname(const JSON_Object *o, const struct Stream *stream, struct StreamPosix *posix) @@ -611,12 +484,7 @@ convert_stream(const JSON_Object *o, const char *name, struct Stream *stream) goto end; } - if (!strcmp(type, "nng")) { - ret = convert_nng_stream(o, &s); - if (ret != 0) { - goto end; - } - } else if (!strcmp(type, "null")) { + if (!strcmp(type, "null")) { s.type = STREAM_TYPE_NULL; } else if (!strcmp(type, "posix")) { ret = convert_posix_stream(o, &s); diff --git a/src/libevp-agent/module_instance_impl.h b/src/libevp-agent/module_instance_impl.h index 8c76d2fe..21f9b5da 100644 --- a/src/libevp-agent/module_instance_impl.h +++ b/src/libevp-agent/module_instance_impl.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -94,7 +95,7 @@ struct module_instance { pthread_t wasm_runner; wasm_module_inst_t wasm_module_inst; char *wasm_runner_exception; - pthread_cond_t exit_condition; + sem_t sem; struct evp_lock lock; enum module_instance_status status; wasm_module_t wasm_module; diff --git a/src/libevp-agent/module_instance_impl_wasm.c b/src/libevp-agent/module_instance_impl_wasm.c index 85ebedf4..e04234ff 100644 --- a/src/libevp-agent/module_instance_impl_wasm.c +++ b/src/libevp-agent/module_instance_impl_wasm.c @@ -65,10 +65,10 @@ module_instance_set_status(struct module_instance *m, { xpthread_mutex_lock(&m->lock); m->status = status; - if (status == MODULE_INSTANCE_STATUS_STOPPED) { - xpthread_cond_signal(&m->exit_condition); - } xpthread_mutex_unlock(&m->lock); + if (status == MODULE_INSTANCE_STATUS_STOPPED && sem_post(&m->sem)) { + xlog_error("sem_post failed with errno %d", errno); + } } static enum module_instance_status @@ -139,7 +139,10 @@ static void impl_post_create(struct module_instance *m) { xpthread_mutex_init(&m->lock); - pthread_cond_init(&m->exit_condition, NULL); + + if (sem_init(&m->sem, 0, 0)) { + xlog_abort("sem_init failed with errno %d", errno); + } module_instance_set_status(m, MODULE_INSTANCE_STATUS_LOADING); @@ -541,40 +544,17 @@ impl_stop(struct module_instance *m) EVP_AGENT_WASM_STOPPED_GRACEFULLY; getrealtime(&max_wait); max_wait.tv_sec += MAX_EXIT_TIME_IN_SECONDS; - xpthread_mutex_lock(&m->lock); - ret = xpthread_cond_timedwait(&m->exit_condition, &m->lock, - &max_wait); - xpthread_mutex_unlock(&m->lock); - if (ret == ETIMEDOUT) { - // timeout: send WASM exception - xlog_warning("Raising WASM exception to exit %s", - m->name); - status = EVP_AGENT_WASM_STOPPED_EXCEPTION; - wasm_runtime_set_exception(m->wasm_module_inst, - "force terminated"); - // wait again for WASM module to exit - max_wait.tv_sec += MAX_EXIT_TIME_IN_SECONDS; - xpthread_mutex_lock(&m->lock); - ret = xpthread_cond_timedwait(&m->exit_condition, - &m->lock, &max_wait); - xpthread_mutex_unlock(&m->lock); - if (ret == ETIMEDOUT) { - // the module still didn't exit: cancel it - xlog_warning("Cancelling thread to exit %s", + while (sem_timedwait(&m->sem, &max_wait)) { + if (errno == ETIMEDOUT) { + xlog_warning("Terminating Wasm instance %s", m->name); - ret = pthread_cancel(m->wasm_runner); - - if (ret != 0) { - xlog_error("pthread_cancel failed: %d", - ret); - } + wasm_runtime_terminate(m->wasm_module_inst); status = EVP_AGENT_WASM_STOPPED_CANCELLED; - } else if (ret != 0) { - xlog_error("xpthread_cond_timedwait error %d", - ret); + } else if (errno != EINTR) { + ret = errno; + xlog_warning("sem_timedwait error %d", ret); + return ret; } - } else if (ret != 0) { - xlog_error("xpthread_cond_timedwait error %d", ret); } ret = pthread_join(m->wasm_runner, NULL); @@ -592,7 +572,9 @@ impl_stop(struct module_instance *m) module_instance_set_status(m, MODULE_INSTANCE_STATUS_STOPPED); xpthread_mutex_destroy(&m->lock); - pthread_cond_destroy(&m->exit_condition); + if (sem_destroy(&m->sem)) { + xlog_abort("sem_destroy failed with errno %d", errno); + } } if (m->wasm_module_inst != NULL) { /* diff --git a/src/libevp-agent/report_refresh.c b/src/libevp-agent/report_refresh.c index 7ebe8fe5..a409e2ae 100644 --- a/src/libevp-agent/report_refresh.c +++ b/src/libevp-agent/report_refresh.c @@ -127,6 +127,7 @@ report_refresh_instance_state(const struct evp_agent_context *agent, const struct evp_hub_context *hub, void *cb_data, intmax_t *qos, enum req_priority *priority) { + size_t len; JSON_Object *states_obj = json_value_get_object(g_evp_global.instance_states); bool *state_updated = cb_data; @@ -139,6 +140,12 @@ report_refresh_instance_state(const struct evp_agent_context *agent, sys_collect_states(agent->sys, convert_state, &args); *state_updated = args.states_updated; + len = json_serialization_size(g_evp_global.instance_states); + + xpthread_mutex_lock(&g_evp_global.instance_states_lock); + g_evp_global.instance_states_len = len; + xpthread_mutex_unlock(&g_evp_global.instance_states_lock); + *qos = 0; *priority = REQ_PRIORITY_LOW; return json_serialize_to_string(g_evp_global.instance_states); diff --git a/src/libevp-agent/sdk.c b/src/libevp-agent/sdk.c index e7450b36..fd3b1947 100644 --- a/src/libevp-agent/sdk.c +++ b/src/libevp-agent/sdk.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -990,12 +991,9 @@ EVP_impl_sendState(struct EVP_client *h, const void *rawbuf, const char *topic, void *userData) { EVP_RESULT ret; - char *name = NULL, *base64 = NULL; size_t len, base64len; bool needs_main_wakeup = false; struct sdk_event_state *state = NULL; - JSON_Value *v = NULL; - JSON_Object *o; /* * FIXME: We check that this new state inserted in the current object @@ -1005,30 +1003,15 @@ EVP_impl_sendState(struct EVP_client *h, const void *rawbuf, const char *topic, * The check is done using a base64 encoding because it is the worst * case between EVP1 and EVP2 way of encoding the state. */ - xasprintf(&name, "state/%s/%s", h->name, topic); - int iret = base64_encode(blob, bloblen, &base64, &base64len); - if (iret != 0) { - xlog_error("Failed to base64-encode blob of length %zu", - bloblen); - free(name); - return EVP_ERROR; - } - v = json_value_deep_copy(g_evp_global.instance_states); - if (v == NULL) { - ret = EVP_NOMEM; - goto end; - } - o = json_value_get_object(v); - if (o == NULL) { - ret = EVP_ERROR; - goto end; - } - if (json_object_set_string(o, name, base64) != JSONSuccess) { - ret = EVP_ERROR; - goto end; - } + base64len = 0; + len = snprintf(NULL, 0, "{ \"state/%s/%s\" : \"\" },\n", h->name, + topic); + mbedtls_base64_encode(NULL, 0, &base64len, blob, bloblen); + len += base64len; - len = json_serialization_size(v); + xpthread_mutex_lock(&g_evp_global.instance_states_lock); + len += g_evp_global.instance_states_len; + xpthread_mutex_unlock(&g_evp_global.instance_states_lock); if (g_mqtt_client == NULL) { ret = EVP_ERROR; @@ -1096,9 +1079,6 @@ EVP_impl_sendState(struct EVP_client *h, const void *rawbuf, const char *topic, ret = EVP_OK; sdk_unlock(); end: - free(base64); - free(name); - json_value_free(v); if (ret) { free(state); } diff --git a/src/libevp-agent/sdk_remote.c b/src/libevp-agent/sdk_remote.c index 3a5b6a5f..1a00c7f7 100644 --- a/src/libevp-agent/sdk_remote.c +++ b/src/libevp-agent/sdk_remote.c @@ -6,6 +6,9 @@ #include #include +#include +#include +#include #include #include @@ -16,9 +19,6 @@ #include "main_loop.h" #include "module_instance.h" #include "sdk_impl.h" -#include "sdkenc/sdk_builder.h" -#include "sdkenc/sdk_reader.h" -#include "sdkenc/sdk_verifier.h" #include "xlog.h" #include "xpthread.h" @@ -752,35 +752,6 @@ add_null_stream_params(const struct Stream *stream, flatcc_builder_t *b) return 0; } -static int -add_nng_stream_params(const struct Stream *stream, flatcc_builder_t *b) -{ - const struct StreamNng *nng = &stream->params.nng; - flatbuffers_ref_t connection = 0; - - connection = flatcc_builder_create_string_str(b, nng->connection); - if (connection == 0) { - xlog_error("flatcc_builder_create_string_str failed"); - return -1; - } - - EVP_SDK_StreamNng_ref_t ref = - ns(StreamNng_create(b, nng->mode, nng->protocol, connection)); - if (ref == 0) { - xlog_warning("StreamNng_create failed"); - return -1; - } - - int error = ns(StreamParamsResponse_params_nng_add(b, ref)); - if (error != 0) { - xlog_warning("StreamParamsResponse_params_add failed: %s", - flatcc_verify_error_string(error)); - return -1; - } - - return 0; -} - static int add_stream_params(const struct Stream *stream, flatcc_builder_t *b) { @@ -801,7 +772,6 @@ add_stream_params(const struct Stream *stream, flatcc_builder_t *b) static int (*const f[])(const struct Stream *, flatcc_builder_t *) = { [STREAM_TYPE_NULL] = add_null_stream_params, - [STREAM_TYPE_NNG] = add_nng_stream_params, }; return f[stream->type](stream, b); diff --git a/src/libevp-agent/sdkrpc/server.c b/src/libevp-agent/sdkrpc/server.c index d60e2a75..a51e8491 100644 --- a/src/libevp-agent/sdkrpc/server.c +++ b/src/libevp-agent/sdkrpc/server.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -19,7 +20,6 @@ #include "../ioutil.h" #include "../sdk_agent.h" -#include "../sdkenc/sdk_builder.h" #include "server.h" void diff --git a/src/libevp-agent/stream/stream.c b/src/libevp-agent/stream/stream.c index dfabe100..497d2f4b 100644 --- a/src/libevp-agent/stream/stream.c +++ b/src/libevp-agent/stream/stream.c @@ -27,9 +27,6 @@ static const struct stream_ops *stream_ops[NR_STREAM_TYPE] = { [STREAM_TYPE_NULL] = &stream_null_ops, [STREAM_TYPE_POSIX] = &stream_posix_ops, -#ifdef CONFIG_EVP_AGENT_LOCAL_SDK_NNG_STREAMS - [STREAM_TYPE_NNG] = &stream_nng_ops, -#endif }; static struct notification notification = @@ -487,25 +484,6 @@ stream_duplicate(const struct Stream *src, struct Stream *dst) switch (src->type) { case STREAM_TYPE_NULL: break; - case STREAM_TYPE_NNG: - { - const struct StreamNng *nng = &src->params.nng; - - connectiondup = strdup(nng->connection); - if (connectiondup == NULL) { - fprintf(stderr, - "strdup(3) failed with errno %d\n", - errno); - ret = errno; - goto end; - } - params.nng = (struct StreamNng){ - .connection = connectiondup, - .mode = nng->mode, - .protocol = nng->protocol, - }; - } - break; case STREAM_TYPE_POSIX: { const struct StreamPosix *posix = &src->params.posix; @@ -557,9 +535,6 @@ stream_free(struct Stream *s) /* TODO: Create virtual function instead of switch */ switch (s->type) { - case STREAM_TYPE_NNG: - free(s->params.nng.connection); - break; case STREAM_TYPE_NULL: break; case STREAM_TYPE_POSIX: diff --git a/src/libevp-agent/stream/stream.h b/src/libevp-agent/stream/stream.h index aaffb4ce..f05a8ef2 100644 --- a/src/libevp-agent/stream/stream.h +++ b/src/libevp-agent/stream/stream.h @@ -20,7 +20,6 @@ struct Stream { char *name; enum StreamType { STREAM_TYPE_NULL, - STREAM_TYPE_NNG, STREAM_TYPE_POSIX, NR_STREAM_TYPE } type; @@ -29,17 +28,6 @@ struct Stream { STREAM_DIRECTION_OUT } direction; union StreamParams { - struct StreamNng { - enum { - STREAM_NNG_MODE_DIAL, - STREAM_NNG_MODE_LISTEN - } mode; - enum { - STREAM_NNG_PROTOCOL_PUSH, - STREAM_NNG_PROTOCOL_PULL - } protocol; - char *connection; - } nng; struct StreamPosix { enum { STREAM_POSIX_TYPE_TCP } type; enum { @@ -140,7 +128,6 @@ EVP_RESULT EVP_impl_streamWrite(struct EVP_client *h, EVP_STREAM stream, const void *buf, size_t n); extern const struct stream_ops stream_null_ops; -extern const struct stream_ops stream_nng_ops; extern const struct stream_ops stream_posix_ops; #endif /* STREAM_H */ diff --git a/src/libevp-agent/sys/sys_collect_responses.c b/src/libevp-agent/sys/sys_collect_responses.c index af047b73..f67aa75f 100644 --- a/src/libevp-agent/sys/sys_collect_responses.c +++ b/src/libevp-agent/sys/sys_collect_responses.c @@ -26,9 +26,10 @@ process_response(struct chan_msg *msg) static int collect(struct SYS_client *c, sys_collect_cb cb, void *user) { - struct sys_response *r; + struct sys_response *r, *next; - for (r = c->resp_head; r; r = r->next) { + for (r = c->resp_head; r; r = next) { + next = r->next; if (cb(r->id, r->response, r->status, user)) { r->reason = SYS_REASON_ERROR; } else { diff --git a/src/libevp-agent/sys/sys_common.c b/src/libevp-agent/sys/sys_common.c index e45a2ca9..76fc816c 100644 --- a/src/libevp-agent/sys/sys_common.c +++ b/src/libevp-agent/sys/sys_common.c @@ -48,7 +48,7 @@ sys_add_headers(struct EVP_BlobRequestHttpExt *req, if (result != EVP_OK) { xlog_error("EVP_BlobRequestHttpExt_addHeader failed " "with %u", - (int)result); + (unsigned int)result); return -1; } } diff --git a/src/libevp-agent/tls.c b/src/libevp-agent/tls.c index 707d91ef..fb5eeb77 100644 --- a/src/libevp-agent/tls.c +++ b/src/libevp-agent/tls.c @@ -150,7 +150,7 @@ xlog_mbedtls_error(int rv, const char *fmt, ...) xlog_error("%s, mbedtls returned -0x%x (%s)", msg, (unsigned int)-rv, buf); } else { - xlog_error("%s, mbedtls returned 0x%x", msg, rv); + xlog_error("%s, mbedtls returned 0x%x", msg, (unsigned int)rv); } } @@ -162,10 +162,11 @@ failed(const char *fn, int rv) if (rv < 0) { char buf[100]; mbedtls_strerror(rv, buf, sizeof(buf)); - xlog_error("%s failed with -0x%x (%s)", fn, -rv, buf); + xlog_error("%s failed with -0x%x (%s)", fn, (unsigned int)-rv, + buf); } else { xlog_error("%s failed, returning a positive value 0x%x", fn, - rv); + (unsigned int)rv); } return rv; } @@ -751,11 +752,11 @@ mbedtls2errno(int rv) xlog_info("mbedtls2errno: converting -0x%x " "(%s) to %d " "(%s)", - -rv, buf, error, strerror(error)); + (unsigned int)-rv, buf, error, strerror(error)); } else { xlog_info("mbedtls2errno: converting 0x%x to " "%d (%s)", - rv, error, strerror(error)); + (unsigned int)rv, error, strerror(error)); } return error; diff --git a/src/libevp-agent/xmqtt.c b/src/libevp-agent/xmqtt.c index 766f8ae9..bea15095 100644 --- a/src/libevp-agent/xmqtt.c +++ b/src/libevp-agent/xmqtt.c @@ -127,11 +127,10 @@ mqtt_prepare_poll(struct mqtt_client *client, bool *want_writep) const time_t now_sec = MQTT_PAL_TIME(); const uint64_t now_ms = gettime_ms(); uint64_t abs_timeout_ms; - fprintf(stderr, - "%s: abs_timeout_sec=%ju, " - "now_sec=%ju\n", - __func__, (uintmax_t)abs_timeout_sec, - (uintmax_t)now_sec); + xlog_info("%s: abs_timeout_sec=%ju, " + "now_sec=%ju\n", + __func__, (uintmax_t)abs_timeout_sec, + (uintmax_t)now_sec); if (abs_timeout_sec >= now_sec) { uint64_t delta_sec = abs_timeout_sec - now_sec; abs_timeout_ms = now_ms + delta_sec * 1000; diff --git a/src/libevp-app-sdk/Makefile b/src/libevp-app-sdk/Makefile index 11384e8c..8f775dd5 100644 --- a/src/libevp-app-sdk/Makefile +++ b/src/libevp-app-sdk/Makefile @@ -6,6 +6,7 @@ PROJECTDIR = ../.. include $(PROJECTDIR)/scripts/rules.mk -include $(PROJECTDIR)/deps.mk +-include $(PROJECTDIR)/.config MORE_CPPFLAGS = \ -I../libevp-agent \ @@ -33,19 +34,23 @@ obj-$(CONFIG_EVP_SDK_SOCKET) += \ sdk.o \ sdkrpc/client.o \ -obj-$(CONFIG_EVP_AGENT_LOCAL_SDK_NNG_STREAMS) += stream/nng.o - LDFLAGS = -L$(LIBDIR) all: libevp-app-sdk.a libevp-app-sdk-bundle.a -libevp-app-sdk.a: $(obj-y) +libevp-app-sdk.o: $(obj-y) $(LD) -r -o $@ $(MORE_LDFLAGS) $(obj-y) -X -x $(OBJCOPY) --keep-global-symbols=symbols.list $@ + +libevp-app-sdk.a: libevp-app-sdk.o + $(AR) $(PROJ_ARFLAGS) $@ $? cp $@ $(LIBDIR) -libevp-app-sdk-bundle.a: libevp-app-sdk.a - $(LD) -r -o $@ $(LDFLAGS) libevp-app-sdk.a $(DEPLIBS) +libevp-app-sdk-bundle.o: libevp-app-sdk.o + $(LD) -r -o $@ $(LDFLAGS) libevp-app-sdk.o $(DEPLIBS) + +libevp-app-sdk-bundle.a: libevp-app-sdk-bundle.o + $(AR) $(PROJ_ARFLAGS) $@ $? cp $@ $(LIBDIR) clean: diff --git a/src/libevp-app-sdk/sdk.c b/src/libevp-app-sdk/sdk.c index bfb1fb65..4b73561e 100644 --- a/src/libevp-app-sdk/sdk.c +++ b/src/libevp-app-sdk/sdk.c @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -20,9 +23,6 @@ #include "path_docker.h" #include "sdk_callback_impl_ops.h" #include "sdk_common.h" -#include "sdkenc/sdk_builder.h" -#include "sdkenc/sdk_reader.h" -#include "sdkenc/sdk_verifier.h" #include "sdkrpc/client.h" #include "sdkutil.h" #include "stream/stream.h" @@ -1012,51 +1012,6 @@ process_null_params(ns(StreamParamsResponse_table_t) body, return EVP_OK; } -static EVP_RESULT -process_nng_params(const ns(StreamParamsResponse_table_t) body, - union StreamParams *p) -{ - EVP_RESULT ret; - char *connectiondup = NULL; - const struct ns(StreamNng_table) *params = - ns(StreamParamsResponse_params(body)); - - if (params == NULL) { - fprintf(stderr, "%s: StreamParamsResponse_params failed\n", - __func__); - ret = EVP_AGENT_PROTOCOL_ERROR; - goto end; - } - - flatbuffers_string_t connection = ns(StreamNng_connection_get(params)); - if (connection == NULL) { - fprintf(stderr, "%s: unexpected null connection\n", __func__); - ret = EVP_AGENT_PROTOCOL_ERROR; - goto end; - } - - connectiondup = strdup(connection); - if (connectiondup == NULL) { - fprintf(stderr, "%s: realloc(3) failed with errno %d\n", - __func__, errno); - ret = EVP_NOMEM; - goto end; - } - - p->nng = (struct StreamNng){ - .mode = ns(StreamNng_mode_get(params)), - .protocol = ns(StreamNng_protocol_get(params)), - .connection = connectiondup, - }; - - ret = EVP_OK; -end: - if (ret != EVP_OK) { - free(connectiondup); - } - return ret; -} - static EVP_RESULT process_stream_response(const struct sdk_request *req, const char *name, struct Stream *stream) @@ -1114,7 +1069,6 @@ process_stream_response(const struct sdk_request *req, const char *name, static EVP_RESULT (*f[])(ns(StreamParamsResponse_table_t), union StreamParams *p) = { [STREAM_TYPE_NULL] = process_null_params, - [STREAM_TYPE_NNG] = process_nng_params, }; if (s.type >= __arraycount(f)) { diff --git a/src/libevp-utils/chan_def.h b/src/libevp-utils/chan_def.h index eea3a265..2d1de88c 100644 --- a/src/libevp-utils/chan_def.h +++ b/src/libevp-utils/chan_def.h @@ -14,7 +14,6 @@ struct chan_item { sem_t sem; - pthread_cond_t cond; struct chan_msg msg; struct chan_item *next; }; diff --git a/src/libevp-utils/chan_item_alloc.c b/src/libevp-utils/chan_item_alloc.c index 686faeec..808022f7 100644 --- a/src/libevp-utils/chan_item_alloc.c +++ b/src/libevp-utils/chan_item_alloc.c @@ -20,12 +20,9 @@ chan_item_alloc(void) if ((it = malloc(sizeof(*it))) == NULL) return NULL; - *it = (struct chan_item){ - .cond = PTHREAD_COND_INITIALIZER, - }; + *it = (struct chan_item){0}; if (sem_init(&it->sem, 0, 0)) { - pthread_cond_destroy(&it->cond); free(it); return NULL; } diff --git a/src/libevp-utils/chan_item_dealloc.c b/src/libevp-utils/chan_item_dealloc.c index 3c413fff..bec960fe 100644 --- a/src/libevp-utils/chan_item_dealloc.c +++ b/src/libevp-utils/chan_item_dealloc.c @@ -19,6 +19,5 @@ chan_item_dealloc(struct chan_item *it) if (!it) return; sem_destroy(&it->sem); - pthread_cond_destroy(&it->cond); free(it); } diff --git a/src/libevp-utils/chan_send.c b/src/libevp-utils/chan_send.c index d63e06c5..e973270d 100644 --- a/src/libevp-utils/chan_send.c +++ b/src/libevp-utils/chan_send.c @@ -32,8 +32,8 @@ chan_send(struct chan *ch, struct chan_msg *msg) /* * synchronous msg, `it->m' is hold * by this thread and we have to wait - * in `it->cond' until the receiver - * signals it and then we can free `it' + * in `it->sem' until the receiver + * posts it and then we can free `it' */ while (sem_wait(&it->sem) && errno == EINTR) diff --git a/src/sdkenc/Makefile b/src/sdkenc/Makefile new file mode 100644 index 00000000..2514fdf6 --- /dev/null +++ b/src/sdkenc/Makefile @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +PROJECTDIR = ../.. + +include $(PROJECTDIR)/scripts/rules.mk + +FLATCC=$(PROJECTDIR)/bin/flatcc + +all: stamp + +stamp: sdk.fbs + $(FLATCC) \ + -a \ + --json-printer \ + sdk.fbs + mkdir -p $(INCDIR)/sdkenc + cp *.h $(INCDIR)/sdkenc + touch $@ + +clean: + rm -f *.h stamp diff --git a/src/sdkenc/sdk.fbs b/src/sdkenc/sdk.fbs new file mode 100644 index 00000000..53581721 --- /dev/null +++ b/src/sdkenc/sdk.fbs @@ -0,0 +1,237 @@ +// SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +namespace EVP.SDK; + +// something like sdk_event + +table Config { + topic:string (required); + blob:[ubyte] (required); +} + +table StateInput { + topic:string (required); + blob:[ubyte] (required); + cb:uint64; // pointer + cb_userdata:uint64; // pointer +} + +table StateOutput { + cb:uint64; // pointer + reason:uint32; + cb_userdata:uint64; // pointer +} + +table Exit { +} + +table BlobRequestAzureBlob { + url:string (required); +} + +table BlobRequestEvp { + remoteName:string (required); + storageName:string; +} + +table BlobRequestHttp { + url:string (required); +} + +table BlobRequestHttpExt { + url:string (required); + headers:[string] (required); +} + +union BlobRequestUnion { + azureBlob:BlobRequestAzureBlob, + evp:BlobRequestEvp, + http:BlobRequestHttp, + http_ext:BlobRequestHttpExt, +} + +table BlobInput { + type:uint32; + op:uint32; + + request:BlobRequestUnion (required); + + filename:string (required); + cb:uint64; // pointer + cb_userdata:uint64; // pointer +} + +table BlobResultAzureBlob { + result:uint32; + error:uint32; + http_status:uint32; +} + +table BlobResultEvp { + result:uint32; + error:uint32; + http_status:uint32; +} + +table BlobResultHttp { + result:uint32; + error:uint32; + http_status:uint32; +} + +table BlobResultHttpExt { + result:uint32; + error:uint32; + http_status:uint32; +} + +union BlobResultUnion { + azureBlob:BlobResultAzureBlob, + evp:BlobResultEvp, + http:BlobResultHttp, + http_ext:BlobResultHttpExt, +} + +table BlobOutput { + result:BlobResultUnion; + + cb:uint64; // pointer + reason:uint32; + cb_userdata:uint64; // pointer +} + +table MessageSentInput { + topic:string (required); + blob:[ubyte] (required); + cb:uint64; // pointer + cb_userdata:uint64; // pointer +} + +table MessageSentOutput { + cb:uint64; // pointer + reason:uint32; + cb_userdata:uint64; // pointer +} + +table MessageReceived { + topic:string (required); + blob:[ubyte] (required); +} + +table TelemetryEntry { + key:string (required); + value:string (required); +} + +table TelemetryInput { + entries:[TelemetryEntry]; + cb:uint64; // pointer + cb_userdata:uint64; // pointer +} + +table TelemetryOutput { + cb:uint64; // pointer + reason:uint32; + cb_userdata:uint64; // pointer +} + +table RpcRequest { + id:uint64; + method:string (required); + params:string (required); +} + +table RpcResponseInput { + id:uint64; + response:string; + status:uint32; + cb:uint64; // pointer + cb_userdata:uint64; // pointer +} + +table RpcResponseOutput { + cb:uint64; // pointer + reason:uint32; + cb_userdata:uint64; // pointer +} + +// ----------- + +union EventBody { + config:Config, + state:StateOutput, + exit:Exit, + blob:BlobOutput, + messageSent:MessageSentOutput, + messageReceived:MessageReceived, + telemetry:TelemetryOutput, + rpcRequest:RpcRequest, + rpcResponse:RpcResponseOutput +} + +table Event { + body:EventBody; +} + +table GetEvent { + timeout_sec:uint64; // time_t + timeout_nsec:uint64; // long +} + +table RequestResendConfig { +} + +union RequestUnion { + getEvent:GetEvent, + sendState:StateInput, + requestResendConfig:RequestResendConfig, + blobOperation:BlobInput, + sendTelemetry:TelemetryInput, + sendMessage:MessageSentInput, + sendRpcResponse:RpcResponseInput, + streamParamsRequest:StreamParamsRequest +} + +table Request { + body:RequestUnion (required); +} + +// ----------- + +table Simple { + result:uint32; // EVP_RESULT +} + +union ResponseUnion { + getEvent:Event, + simple:Simple, + streamParamsResponse:StreamParamsResponse, +} + +table Response { + body:ResponseUnion (required); +} + +table StreamParamsRequest { + name:string; +} + +// This must match the definition in src/stream.h. +enum StreamType : byte { + Null, +} + +// This must match the definition in src/stream.h. +enum StreamDirection : byte { + In, + Out +} + +table StreamParamsResponse { + result:uint32; // EVP_RESULT + // Only valid if EVP_RESULT == EVP_OK + type:StreamType; + direction:StreamDirection; +} diff --git a/test/certs/Makefile b/test/certs/Makefile index 2af95373..46f313bc 100644 --- a/test/certs/Makefile +++ b/test/certs/Makefile @@ -23,7 +23,7 @@ ca-cert.pem: ca-key.pem -out $@ \ -sha256 \ -noenc \ - -subj "/C=XX/ST=Barcelona/L=Barcelona/O=Midokura/CN=CA" + -subj "/C=XX/ST=Barcelona/L=Barcelona/O=SSS/CN=CA" server-key.pem: @echo Generating $@ @@ -41,7 +41,7 @@ server.csr: server-key.pem -key server-key.pem \ -sha256 \ -noenc \ - -subj "/C=XX/ST=Barcelona/L=Barcelona/O=Midokura/CN=localhost" + -subj "/C=XX/ST=Barcelona/L=Barcelona/O=SSS/CN=localhost" server-cert.pem: server.csr ca-cert.pem ca-key.pem @echo Generating $@ diff --git a/test/src/systest/test_sysapp_telemetry.c b/test/src/systest/test_sysapp_telemetry.c index 2cc8844e..85855c4d 100644 --- a/test/src/systest/test_sysapp_telemetry.c +++ b/test/src/systest/test_sysapp_telemetry.c @@ -30,6 +30,7 @@ struct test { struct evp_agent_context *ctxt; pthread_t thread; + pthread_mutex_t mtx; enum SYS_result result; struct SYS_client *c; sem_t sem; @@ -121,8 +122,13 @@ void * __wrap_strdup(const char *s) { void *__real_strdup(const char *); + bool fail; - if (g_test.strdup_fail) + assert(!pthread_mutex_lock(&g_test.mtx)); + fail = g_test.strdup_fail; + assert(!pthread_mutex_unlock(&g_test.mtx)); + + if (fail) return NULL; return __real_strdup(s); @@ -136,6 +142,7 @@ __wrap_sys_collect_telemetry(struct sys_group *gr, sys_telemetry_collect cb, sys_telemetry_collect, void *); int ret; + assert(!pthread_mutex_lock(&g_test.mtx)); if (g_test.fail) { g_test.strdup_fail = true; } @@ -145,6 +152,7 @@ __wrap_sys_collect_telemetry(struct sys_group *gr, sys_telemetry_collect cb, ret = __real_sys_collect_telemetry(gr, cb, user); g_test.strdup_fail = false; + assert(!pthread_mutex_unlock(&g_test.mtx)); return ret; } @@ -167,7 +175,9 @@ setup(void **state) { struct test *test = *state; + assert(!pthread_mutex_lock(&g_test.mtx)); test->fail = false; + assert(!pthread_mutex_unlock(&g_test.mtx)); return setup_common(test); } @@ -176,7 +186,9 @@ setup_error(void **state) { struct test *test = *state; + assert(!pthread_mutex_lock(&g_test.mtx)); test->fail = true; + assert(!pthread_mutex_unlock(&g_test.mtx)); return setup_common(test); } @@ -184,6 +196,8 @@ static int suite_setup(void **state) { struct test *test = &g_test; + int error; + pthread_mutexattr_t attr; if (sem_init(&test->sem, 0, 0)) { fprintf(stderr, "%s: sem_init(3): %s\n", __func__, @@ -191,6 +205,25 @@ suite_setup(void **state) return -1; } + if ((error = pthread_mutexattr_init(&attr))) { + fprintf(stderr, "%s: pthread_mutexattr_init(3): %s\n", + __func__, strerror(error)); + return -1; + } + + if ((error = pthread_mutexattr_settype(&attr, + PTHREAD_MUTEX_RECURSIVE))) { + fprintf(stderr, "%s: pthread_mutexattr_settype(3): %s\n", + __func__, strerror(error)); + return -1; + } + + if ((error = pthread_mutex_init(&test->mtx, &attr))) { + fprintf(stderr, "%s: pthread_mutex_init(3): %s\n", __func__, + strerror(error)); + return -1; + } + agent_test_setup(); test->ctxt = agent_test_start(); @@ -207,6 +240,7 @@ static int suite_teardown(void **state) { struct test *test = *state; + int error; if (sem_destroy(&test->sem)) { fprintf(stderr, "%s: sem_destroy(3): %s\n", __func__, @@ -215,6 +249,13 @@ suite_teardown(void **state) } agent_test_exit(); + + if ((error = pthread_mutex_destroy(&test->mtx))) { + fprintf(stderr, "%s: pthread_mutex_destroy(3): %s\n", __func__, + strerror(error)); + return -1; + } + return 0; } diff --git a/test/src/systest/test_wasm_mod_streams.c b/test/src/systest/test_wasm_mod_streams.c index a9eff333..868ea224 100644 --- a/test/src/systest/test_wasm_mod_streams.c +++ b/test/src/systest/test_wasm_mod_streams.c @@ -6,9 +6,6 @@ #include #include -#include -#include -#include #include #include #include @@ -31,29 +28,23 @@ enum test_wasm_config_echo_payloads { DEPLOYMENT_MANIFEST_1, DEPLOYMENT_MANIFEST_2, - DEPLOYMENT_MANIFEST_3, - DEPLOYMENT_MANIFEST_4, EMPTY_DEPLOYMENT_MANIFEST_1, INSTANCE_CONFIG_1 }; -#define TEST_EMPTY_DEPLOYMENT_ID1 "d2862453-f57e-4ddb-90d2-d470c27f6a92" -#define TEST_DEPLOYMENT_ID1 "4fa905ae-e103-46ab-a8b9-73be07599708" -#define TEST_DEPLOYMENT_ID2 "0f40626e-5d98-4472-ad4e-a4fb1490b382" -#define TEST_DEPLOYMENT_ID3 "f5cb7e2d-4e23-4bc3-bd48-845945de3456" -#define TEST_DEPLOYMENT_ID4 "79e98832-23c7-4733-b656-b49a24e33c89" +#define TEST_EMPTY_DEPLOYMENT_ID "d2862453-f57e-4ddb-90d2-d470c27f6a92" +#define TEST_DEPLOYMENT_ID1 "f5cb7e2d-4e23-4bc3-bd48-845945de3456" +#define TEST_DEPLOYMENT_ID2 "79e98832-23c7-4733-b656-b49a24e33c89" -#define READER_INSTANCE_ID "10709a54-1d35-4955-b087-2380863f7eea" -#define READER_INSTANCE_ID2 "1fddfca9-0607-40f6-8e87-661d9f366424" -#define READER_MODULE_ID "0329dea0-bd16-4e8a-be29-cd415c1a10ff" -#define READER_MODULE_PATH "../test_modules/stream_reader.wasm" +#define READER_INSTANCE_ID "1fddfca9-0607-40f6-8e87-661d9f366424" +#define READER_MODULE_ID "0329dea0-bd16-4e8a-be29-cd415c1a10ff" +#define READER_MODULE_PATH "../test_modules/stream_reader.wasm" #define READER_MODULE_HASH \ "f0464cf80c305261400ebc744571d6cff6968907cc53b24529c1ababfd7aabeb" -#define WRITER_INSTANCE_ID "4a3737bd-98ea-4675-b9f8-336c59bacf78" -#define WRITER_INSTANCE_ID2 "bc7b3156-5651-4efe-8743-ca763e0f2b15" -#define WRITER_MODULE_ID "a2f149eb-3c53-4d02-88af-d0838aa12dcb" -#define WRITER_MODULE_PATH "../test_modules/stream_writer.wasm" +#define WRITER_INSTANCE_ID "bc7b3156-5651-4efe-8743-ca763e0f2b15" +#define WRITER_MODULE_ID "a2f149eb-3c53-4d02-88af-d0838aa12dcb" +#define WRITER_MODULE_PATH "../test_modules/stream_writer.wasm" #define WRITER_MODULE_HASH \ "5b02344d79409668d1da54d50e852380faf98728facbedb0140bb176fe4bdd56" @@ -69,102 +60,6 @@ enum test_wasm_config_echo_payloads { " \"direction\": \"in\"," \ " \"parameters\": {" \ " " \ - "\"connection_string\": \"tcp://127.0.0.1:0\"," \ - " \"mode\": " \ - "\"listen\"," \ - " \"protocol\": " \ - "\"pull\"" \ - " }," \ - " \"type\": \"nng\"" \ - " }" \ - " }," \ - " \"subscribe\": {}" \ - " }" \ - " }," \ - " \"modules\": {" \ - " \"" READER_MODULE_ID "\": {" \ - " \"downloadUrl\": \"file://" READER_MODULE_PATH "\"," \ - " \"entryPoint\": \"main\"," \ - " \"hash\": \"" READER_MODULE_HASH "\"," \ - " \"moduleImpl\": \"wasm\"" \ - " }" \ - " }," \ - " \"publishTopics\": {}," \ - " \"subscribeTopics\": {}" \ - "}" - -#define EVP2_DEPLOYMENT_MANIFEST_2 \ - "{" \ - " \"deploymentId\": \"" TEST_DEPLOYMENT_ID2 "\"," \ - " \"instanceSpecs\": {" \ - " \"" READER_INSTANCE_ID "\": {" \ - " \"moduleId\": \"" READER_MODULE_ID "\"," \ - " \"publish\": {}," \ - " \"streams\": {" \ - " \"in-video-stream\": {" \ - " \"direction\": \"in\"," \ - " \"parameters\": {" \ - " " \ - "\"connection_string\": \"tcp://127.0.0.1:0\"," \ - " \"mode\": " \ - "\"listen\"," \ - " \"protocol\": " \ - "\"pull\"" \ - " }," \ - " \"type\": \"nng\"" \ - " }" \ - " }," \ - " \"subscribe\": {}" \ - " }," \ - " \"" WRITER_INSTANCE_ID "\": {" \ - " \"moduleId\": \"" WRITER_MODULE_ID "\"," \ - " \"publish\": {}," \ - " \"streams\": {" \ - " \"out-video-stream\": {" \ - " \"direction\": \"out\"," \ - " \"parameters\": {" \ - " " \ - "\"connection_string\": \"tcp://127.0.0.1:%hu\"," \ - " \"mode\": \"dial\"," \ - " \"protocol\": " \ - "\"push\"" \ - " }," \ - " \"type\": \"nng\"" \ - " }" \ - " }," \ - " \"subscribe\": {}" \ - " }" \ - " }," \ - " \"modules\": {" \ - " \"" READER_MODULE_ID "\": {" \ - " \"downloadUrl\": \"file://" READER_MODULE_PATH "\"," \ - " \"entryPoint\": \"main\"," \ - " \"hash\": \"" READER_MODULE_HASH "\"," \ - " \"moduleImpl\": \"wasm\"" \ - " }," \ - " \"" WRITER_MODULE_ID "\": {" \ - " \"downloadUrl\": \"file://" WRITER_MODULE_PATH "\"," \ - " \"entryPoint\": \"main\"," \ - " \"hash\": \"" WRITER_MODULE_HASH "\"," \ - " \"moduleImpl\": \"wasm\"" \ - " }" \ - " }," \ - " \"publishTopics\": {}," \ - " \"subscribeTopics\": {}" \ - "}" - -#define EVP2_DEPLOYMENT_MANIFEST_3 \ - "{" \ - " \"deploymentId\": \"" TEST_DEPLOYMENT_ID3 "\"," \ - " \"instanceSpecs\": {" \ - " \"" READER_INSTANCE_ID2 "\": {" \ - " \"moduleId\": \"" READER_MODULE_ID "\"," \ - " \"publish\": {}," \ - " \"streams\": {" \ - " \"in-video-stream\": {" \ - " \"direction\": \"in\"," \ - " \"parameters\": {" \ - " " \ "\"hostname\": \"127.0.0.1\"," \ "\"port\": \"0\"," \ "\"domain\": \"IPv4\"," \ @@ -188,11 +83,11 @@ enum test_wasm_config_echo_payloads { " \"subscribeTopics\": {}" \ "}" -#define EVP2_DEPLOYMENT_MANIFEST_4 \ +#define EVP2_DEPLOYMENT_MANIFEST_2 \ "{" \ - " \"deploymentId\": \"" TEST_DEPLOYMENT_ID4 "\"," \ + " \"deploymentId\": \"" TEST_DEPLOYMENT_ID2 "\"," \ " \"instanceSpecs\": {" \ - " \"" READER_INSTANCE_ID2 "\": {" \ + " \"" READER_INSTANCE_ID "\": {" \ " \"moduleId\": \"" READER_MODULE_ID "\"," \ " \"publish\": {}," \ " \"streams\": {" \ @@ -210,7 +105,7 @@ enum test_wasm_config_echo_payloads { " }," \ " \"subscribe\": {}" \ " }," \ - " \"" WRITER_INSTANCE_ID2 "\": {" \ + " \"" WRITER_INSTANCE_ID "\": {" \ " \"moduleId\": \"" WRITER_MODULE_ID "\"," \ " \"publish\": {}," \ " \"streams\": {" \ @@ -249,7 +144,7 @@ enum test_wasm_config_echo_payloads { #define EVP2_EMPTY_DEPLOYMENT_MANIFEST_1 \ "{" \ - " \"deploymentId\": \"" TEST_EMPTY_DEPLOYMENT_ID1 "\"," \ + " \"deploymentId\": \"" TEST_EMPTY_DEPLOYMENT_ID "\"," \ " \"instanceSpecs\": {}," \ " \"modules\": {}," \ " \"publishTopics\": {}," \ @@ -276,10 +171,10 @@ send_deployment(struct evp_agent_context *ctxt, const char *payload) } } -static char *evp2_deployment2; +static char *evp2_deployment; static void -test_wasm_mod_streams_nng(void **state) +test_wasm_mod_streams_posix(void **state) { struct evp_agent_context *ctxt = *state; const char *iot = getenv("EVP_IOT_PLATFORM"); @@ -309,15 +204,16 @@ test_wasm_mod_streams_nng(void **state) sdk_unlock(); assert_non_null(h); + struct stream_impl *si = stream_from_name(h, "in-video-stream"); assert_non_null(si); assert_ptr_equal(si, p.si); - xasprintf(&evp2_deployment2, EVP2_DEPLOYMENT_MANIFEST_2, p.port); + xasprintf(&evp2_deployment, EVP2_DEPLOYMENT_MANIFEST_2, p.port); agent_register_payload(DEPLOYMENT_MANIFEST_2, EVP_HUB_TYPE_EVP2_TB, - evp2_deployment2); + evp2_deployment); agent_send_deployment(ctxt, agent_get_payload(DEPLOYMENT_MANIFEST_2)); @@ -335,70 +231,7 @@ test_wasm_mod_streams_nng(void **state) agent_poll(verify_json, "deploymentStatus.deploymentId=%s," "deploymentStatus.reconcileStatus=%s", - TEST_EMPTY_DEPLOYMENT_ID1, "ok"); -} - -static char *evp2_deployment4; - -static void -test_wasm_mod_streams_posix(void **state) -{ - struct evp_agent_context *ctxt = *state; - const char *iot = getenv("EVP_IOT_PLATFORM"); - assert_non_null(iot); - - if (!strcmp(iot, "EVP1")) { - skip(); - } - - struct stream_port p; - struct notification_entry *e; - struct notification *n = stream_notification(); - - assert_non_null(n); - assert_int_equal( - notification_subscribe(n, "init/port", on_port, &p, &e), 0); - - send_deployment(ctxt, agent_get_payload(DEPLOYMENT_MANIFEST_3)); - - agent_poll(verify_json, - "deploymentStatus.deploymentId=%s," - "deploymentStatus.reconcileStatus=%s", - TEST_DEPLOYMENT_ID3, "ok"); - - sdk_lock(); - struct EVP_client *h = sdk_handle_from_name(READER_INSTANCE_ID2); - sdk_unlock(); - - assert_non_null(h); - - struct stream_impl *si = stream_from_name(h, "in-video-stream"); - - assert_non_null(si); - assert_ptr_equal(si, p.si); - - xasprintf(&evp2_deployment4, EVP2_DEPLOYMENT_MANIFEST_4, p.port); - - agent_register_payload(DEPLOYMENT_MANIFEST_4, EVP_HUB_TYPE_EVP2_TB, - evp2_deployment4); - - agent_send_deployment(ctxt, agent_get_payload(DEPLOYMENT_MANIFEST_4)); - - agent_poll(verify_json, - "deploymentStatus.deploymentId=%s," - "deploymentStatus.reconcileStatus=%s", - TEST_DEPLOYMENT_ID4, "ok"); - - agent_poll(verify_contains, "stream-read-ok"); - assert_int_equal(notification_unsubscribe(n, e), 0); - - // send empty deployment - send_deployment(ctxt, agent_get_payload(EMPTY_DEPLOYMENT_MANIFEST_1)); - - agent_poll(verify_json, - "deploymentStatus.deploymentId=%s," - "deploymentStatus.reconcileStatus=%s", - TEST_EMPTY_DEPLOYMENT_ID1, "ok"); + TEST_EMPTY_DEPLOYMENT_ID, "ok"); } static int @@ -407,8 +240,7 @@ teardown(void **state) // wait for agent to finish agent_test_exit(); - free(evp2_deployment2); - free(evp2_deployment4); + free(evp2_deployment); return 0; } @@ -444,9 +276,6 @@ setup(void **state) agent_register_payload(DEPLOYMENT_MANIFEST_1, EVP_HUB_TYPE_EVP2_TB, EVP2_DEPLOYMENT_MANIFEST_1); - - agent_register_payload(DEPLOYMENT_MANIFEST_3, EVP_HUB_TYPE_EVP2_TB, - EVP2_DEPLOYMENT_MANIFEST_3); return 0; } @@ -455,7 +284,6 @@ main(void) { // define tests const struct CMUnitTest tests[] = { - cmocka_unit_test(test_wasm_mod_streams_nng), cmocka_unit_test(test_wasm_mod_streams_posix), }; // setup, run tests and teardown diff --git a/test/src/ut-nohub/test_sdkenc.c b/test/src/ut-nohub/test_sdkenc.c index d7731823..c81603b6 100644 --- a/test/src/ut-nohub/test_sdkenc.c +++ b/test/src/ut-nohub/test_sdkenc.c @@ -5,6 +5,9 @@ */ #include +#include +#include +#include #include #include #include @@ -15,9 +18,6 @@ #include #include "hub.h" -#include "sdk_builder.h" -#include "sdk_reader.h" -#include "sdk_verifier.h" #undef ns #define ns(a) FLATBUFFERS_WRAP_NAMESPACE(EVP_SDK, a) diff --git a/tools/fortify/filter-agent.txt b/tools/fortify/filter-agent.txt index b543e5a8..02ee3623 100644 --- a/tools/fortify/filter-agent.txt +++ b/tools/fortify/filter-agent.txt @@ -187,79 +187,6 @@ F4BC0DB59A449AD000146D1FF3F6A717 # VariableAccess: tmpmax [req.c(133)] EC3A8A0AD55E3A2C4FF67D7A5EB5A853 -# False positive. -# Yet again, Fortify fails to see the ownership for nng is transferred to -# si->params if successful, or freed otherwise. -# [1A885094842BD658D060434C33161244 : high : Memory Leak : controlflow ] -# -# stream/nng.c(81) : start -> allocated : nng = malloc(...) -# stream/nng.c(81) : allocated -> allocated : nng refers to dynamically allocated memory -# stream/nng.c(83) : Branch not taken: (nng != NULL) -# stream/nng.c(102) : Branch taken: (cfg->protocol == 1) -# stream/nng.c(102) : goto -# stream/nng.c(104) : Branch taken: (error != 0) -# stream/nng.c(107) : allocated -> allocated : return -# stream/nng.c(107) : allocated -> allocated : nng no longer refers to dynamically allocated memory -# stream/nng.c(107) : allocated -> leak : nng end scope : Memory leaked -# -# stream/nng.c(81) : start -> allocated : nng = malloc(...) -# stream/nng.c(81) : allocated -> allocated : nng refers to dynamically allocated memory -# stream/nng.c(83) : Branch not taken: (nng != NULL) -# stream/nng.c(93) : Default case -# stream/nng.c(112) : Branch taken: (cfg->mode == 0) -# stream/nng.c(112) : goto -# stream/nng.c(115) : Branch taken: (error != 0) -# stream/nng.c(118) : allocated -> allocated : return -# stream/nng.c(118) : allocated -> allocated : nng no longer refers to dynamically allocated memory -# stream/nng.c(118) : allocated -> leak : nng end scope : Memory leaked -# -# stream/nng.c(81) : start -> allocated : nng = malloc(...) -# stream/nng.c(81) : allocated -> allocated : nng refers to dynamically allocated memory -# stream/nng.c(83) : Branch not taken: (nng != NULL) -# stream/nng.c(93) : Default case -# stream/nng.c(128) : Branch taken: (cfg->mode == 1) -# stream/nng.c(128) : goto -# stream/nng.c(131) : Branch taken: (error != 0) -# stream/nng.c(134) : allocated -> allocated : return -# stream/nng.c(134) : allocated -> allocated : nng no longer refers to dynamically allocated memory -# stream/nng.c(134) : allocated -> leak : nng end scope : Memory leaked -# -# stream/nng.c(81) : start -> allocated : nng = malloc(...) -# stream/nng.c(81) : allocated -> allocated : nng refers to dynamically allocated memory -# stream/nng.c(83) : Branch not taken: (nng != NULL) -# stream/nng.c(94) : Branch taken: (cfg->protocol == 0) -# stream/nng.c(94) : goto -# stream/nng.c(96) : Branch taken: (error != 0) -# stream/nng.c(99) : goto -# stream/nng.c(148) : Branch not taken: (ret == 0) -# stream/nng.c(154) : allocated -> allocated : nng no longer refers to dynamically allocated memory -# stream/nng.c(154) : allocated -> leak : nng end scope : Memory leaked -# -# stream/nng.c(81) : start -> allocated : nng = malloc(...) -# stream/nng.c(81) : allocated -> allocated : nng refers to dynamically allocated memory -# stream/nng.c(83) : Branch not taken: (nng != NULL) -# stream/nng.c(93) : Default case -# stream/nng.c(112) : Branch taken: (cfg->mode == 0) -# stream/nng.c(112) : goto -# stream/nng.c(115) : Branch not taken: (error == 0) -# stream/nng.c(122) : Branch taken: (error != 0) -# stream/nng.c(125) : allocated -> allocated : return -# stream/nng.c(125) : allocated -> allocated : nng no longer refers to dynamically allocated memory -# stream/nng.c(125) : allocated -> leak : nng end scope : Memory leaked -# -# stream/nng.c(81) : start -> allocated : nng = malloc(...) -# stream/nng.c(81) : allocated -> allocated : nng refers to dynamically allocated memory -# stream/nng.c(83) : Branch not taken: (nng != NULL) -# stream/nng.c(93) : Default case -# stream/nng.c(128) : Branch taken: (cfg->mode == 1) -# stream/nng.c(128) : goto -# stream/nng.c(131) : Branch not taken: (error == 0) -# stream/nng.c(138) : Branch taken: (error != 0) -# stream/nng.c(141) : allocated -> allocated : return -# stream/nng.c(141) : allocated -> allocated : nng no longer refers to dynamically allocated memory -# stream/nng.c(141) : allocated -> leak : nng end scope : Memory leaked -1A885094842BD658D060434C33161244 - # False positive. # Yet again, Fortify fails to see the ownership for si is transferred on the # call to stream_insert when successful, or freed otherwise. @@ -305,65 +232,69 @@ EC3A8A0AD55E3A2C4FF67D7A5EB5A853 # Filtering flatbuffers issues # ########################################################## -# [6EBADB667319025D962EA0A1E48D58DC : high : Integer Overflow : dataflow ] -# libevp-agent/sdk_remote.c(559) : ->malloc(0) -# libevp-agent/sdk_remote.c(554) : <=> (nentries) -# libevp-agent/sdkenc/sdk_reader.h(897) : return -# flatcc/include/flatcc/flatcc_endian.h(87) : return -# flatcc/include/flatcc/flatcc_endian.h(87) : return +# [994C38F53DC53FA3194741CAC501D7A2 : high : Integer Overflow : dataflow ] +# sdk_remote.c(567) : ->malloc(0) +# sdk_remote.c(562) : <=> (nentries) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(832) : return +# /__w/wedge-agent/wedge-agent/include/flatcc/flatcc_endian.h(87) : return +# /__w/wedge-agent/wedge-agent/include/flatcc/flatcc_endian.h(87) : return # /usr/include/x86_64-linux-gnu/bits/uintn-identity.h(41) : return (__x) -# flatcc/include/flatcc/flatcc_endian.h(87) : <->__uint32_identity(0->return) -# flatcc/include/flatcc/flatcc_endian.h(87) : <->__flatbuffers_uoffset_cast_from_pe(0->return) -# libevp-agent/sdkenc/sdk_reader.h(897) : <->__flatbuffers_uoffset_read_from_pe(0->return) -# libevp-agent/sdk_remote.c(554) : <->EVP_SDK_TelemetryEntry_vec_len(0->return) -# libevp-agent/sdk_remote.c(553) : <=> (vec) -# libevp-agent/sdkenc/sdk_reader.h(913) : return -# libevp-agent/sdkenc/sdk_reader.h(913) : <=> (elem__tmp) -# libevp-agent/sdk_remote.c(553) : <->EVP_SDK_TelemetryInput_entries(0->return) -# libevp-agent/sdk_remote.c(550) : <=> (t) -# libevp-agent/sdkenc/sdk_reader.h(1098) : return -# libevp-agent/sdkenc/sdk_reader.h(1098) : <=> (elem__tmp) -# libevp-agent/sdk_remote.c(550) : <->EVP_SDK_Request_body(0->return) -# libevp-agent/sdk_remote.c(969) : ->process_send_telemetry(1) -# libevp-agent/sdk_remote.c(926) : <=> (req) -# libevp-agent/sdkenc/sdk_reader.h(1096) : return -# libevp-agent/sdk_remote.c(926) : <->EVP_SDK_Request_as_root(0->return) -# libevp-agent/sdkrpc/server.c(96) : ->sdk_process_request(0) -# libevp-agent/sdkrpc/server.c(85) : <- readall(1) -# libevp-agent/ioutil.c(28) : <- read(1) -6EBADB667319025D962EA0A1E48D58DC - -# [974D927872FA4C2E2EBCCFD5EFAD10E6 : high : Integer Overflow : dataflow ] -# libevp-agent/sdk_remote.c(496) : ->calloc(0) -# libevp-agent/sdk_remote.c(493) : <=> (http_ext_request.nheaders) -# libevp-agent/sdkenc/flatbuffers_common_reader.h(135) : return -# flatcc/include/flatcc/flatcc_endian.h(87) : return -# flatcc/include/flatcc/flatcc_endian.h(87) : return +# /__w/wedge-agent/wedge-agent/include/flatcc/flatcc_endian.h(87) : <->__uint32_identity(0->return) +# /__w/wedge-agent/wedge-agent/include/flatcc/flatcc_endian.h(87) : <->__flatbuffers_uoffset_cast_from_pe(0->return) +# /__w/wedge-agent/wedge-agent/include/flatcc/flatcc_endian.h(87) : return (p) +# /__w/wedge-agent/wedge-agent/include/flatcc/flatcc_endian.h(87) : <->__flatbuffers_uoffset_read(0->return) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(832) : <->__flatbuffers_uoffset_read_from_pe(0->return) +# sdk_remote.c(562) : <->EVP_SDK_TelemetryEntry_vec_len(0->return) +# sdk_remote.c(561) : <=> (vec) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(848) : return +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(848) : <=> (elem__tmp) +# sdk_remote.c(561) : <->EVP_SDK_TelemetryInput_entries(0->return) +# sdk_remote.c(558) : <=> (t) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1033) : return +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1033) : <=> (elem__tmp) +# sdk_remote.c(558) : <->EVP_SDK_Request_body(0->return) +# sdk_remote.c(952) : ->process_send_telemetry(1) +# sdk_remote.c(909) : <=> (req) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1031) : return +# sdk_remote.c(909) : <->EVP_SDK_Request_as_root(0->return) +# sdkrpc/server.c(96) : ->sdk_process_request(0) +# sdkrpc/server.c(85) : <- readall(1) +# ioutil.c(22) : <- read(1) +994C38F53DC53FA3194741CAC501D7A2 + +# [C4E975D3F24A6B555BDF5CAB0D8F241B : high : Integer Overflow : dataflow ] +# sdk_remote.c(504) : ->calloc(0) +# sdk_remote.c(501) : <=> (http_ext_request.nheaders) +# /__w/wedge-agent/wedge-agent/include/sdkenc/flatbuffers_common_reader.h(135) : return +# /__w/wedge-agent/wedge-agent/include/flatcc/flatcc_endian.h(87) : return +# /__w/wedge-agent/wedge-agent/include/flatcc/flatcc_endian.h(87) : return # /usr/include/x86_64-linux-gnu/bits/uintn-identity.h(41) : return (__x) -# flatcc/include/flatcc/flatcc_endian.h(87) : <->__uint32_identity(0->return) -# flatcc/include/flatcc/flatcc_endian.h(87) : <->__flatbuffers_uoffset_cast_from_pe(0->return) -# libevp-agent/sdkenc/flatbuffers_common_reader.h(135) : <->__flatbuffers_uoffset_read_from_pe(0->return) -# libevp-agent/sdk_remote.c(494) : <->flatbuffers_string_vec_len(0->return) -# libevp-agent/sdk_remote.c(491) : <=> (headers_vec) -# libevp-agent/sdkenc/sdk_reader.h(714) : return -# libevp-agent/sdkenc/sdk_reader.h(714) : <=> (elem__tmp) -# libevp-agent/sdk_remote.c(492) : <->EVP_SDK_BlobRequestHttpExt_headers(0->return) -# libevp-agent/sdk_remote.c(483) : <=> (http_ext) -# libevp-agent/sdkenc/sdk_reader.h(759) : return -# libevp-agent/sdkenc/sdk_reader.h(759) : <=> (elem__tmp) -# libevp-agent/sdk_remote.c(484) : <->EVP_SDK_BlobInput_request(0->return) -# libevp-agent/sdk_remote.c(414) : <=> (blob) -# libevp-agent/sdkenc/sdk_reader.h(1098) : return -# libevp-agent/sdkenc/sdk_reader.h(1098) : <=> (elem__tmp) -# libevp-agent/sdk_remote.c(414) : <->EVP_SDK_Request_body(0->return) -# libevp-agent/sdk_remote.c(969) : ->process_blob_operation(1) -# libevp-agent/sdk_remote.c(926) : <=> (req) -# libevp-agent/sdkenc/sdk_reader.h(1096) : return -# libevp-agent/sdk_remote.c(926) : <->EVP_SDK_Request_as_root(0->return) -# libevp-agent/sdkrpc/server.c(96) : ->sdk_process_request(0) -# libevp-agent/sdkrpc/server.c(85) : <- readall(1) -# libevp-agent/ioutil.c(28) : <- read(1) -974D927872FA4C2E2EBCCFD5EFAD10E6 +# /__w/wedge-agent/wedge-agent/include/flatcc/flatcc_endian.h(87) : <->__uint32_identity(0->return) +# /__w/wedge-agent/wedge-agent/include/flatcc/flatcc_endian.h(87) : <->__flatbuffers_uoffset_cast_from_pe(0->return) +# /__w/wedge-agent/wedge-agent/include/flatcc/flatcc_endian.h(87) : return (p) +# /__w/wedge-agent/wedge-agent/include/flatcc/flatcc_endian.h(87) : <->__flatbuffers_uoffset_read(0->return) +# /__w/wedge-agent/wedge-agent/include/sdkenc/flatbuffers_common_reader.h(135) : <->__flatbuffers_uoffset_read_from_pe(0->return) +# sdk_remote.c(502) : <->flatbuffers_string_vec_len(0->return) +# sdk_remote.c(499) : <=> (headers_vec) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(649) : return +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(649) : <=> (elem__tmp) +# sdk_remote.c(500) : <->EVP_SDK_BlobRequestHttpExt_headers(0->return) +# sdk_remote.c(491) : <=> (http_ext) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(694) : return +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(694) : <=> (elem__tmp) +# sdk_remote.c(492) : <->EVP_SDK_BlobInput_request(0->return) +# sdk_remote.c(422) : <=> (blob) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1033) : return +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1033) : <=> (elem__tmp) +# sdk_remote.c(422) : <->EVP_SDK_Request_body(0->return) +# sdk_remote.c(952) : ->process_blob_operation(1) +# sdk_remote.c(909) : <=> (req) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1031) : return +# sdk_remote.c(909) : <->EVP_SDK_Request_as_root(0->return) +# sdkrpc/server.c(96) : ->sdk_process_request(0) +# sdkrpc/server.c(85) : <- readall(1) +# ioutil.c(22) : <- read(1) +C4E975D3F24A6B555BDF5CAB0D8F241B ################## # MQTT-C related # @@ -592,16 +523,16 @@ B838E55D9366945FE643B14028366303 # And in this branch there is the free # sdk_remote.c(491) ==> free(entries); # -# [6BAB7EEBA1E6EBF51D76071F2CBF4A74 : high : Memory Leak : controlflow ] +# [52F5843BA1269E1A5925D903D288954D : high : Memory Leak : controlflow ] # -# libevp-agent/sdk_remote.c(552) : Branch taken: (t != NULL) -# libevp-agent/sdk_remote.c(558) : start -> allocated : entries = malloc(...) -# libevp-agent/sdk_remote.c(558) : allocated -> allocated : entries refers to dynamically allocated memory -# libevp-agent/sdk_remote.c(560) : Branch not taken: (entries != NULL) -# libevp-agent/sdk_remote.c(579) : Branch not taken: (0 == ret) -# libevp-agent/sdk_remote.c(596) : allocated -> allocated : entries no longer refers to dynamically allocated memory -# libevp-agent/sdk_remote.c(596) : allocated -> leak : entries end scope : Memory leaked -6BAB7EEBA1E6EBF51D76071F2CBF4A74 +# sdk_remote.c(560) : Branch taken: (t != NULL) +# sdk_remote.c(566) : start -> allocated : entries = malloc(...) +# sdk_remote.c(566) : allocated -> allocated : entries refers to dynamically allocated memory +# sdk_remote.c(568) : Branch not taken: (entries != NULL) +# sdk_remote.c(587) : Branch not taken: (0 == ret) +# sdk_remote.c(604) : allocated -> allocated : entries no longer refers to dynamically allocated memory +# sdk_remote.c(604) : allocated -> leak : entries end scope : Memory leaked +52F5843BA1269E1A5925D903D288954D # The EVP SDK (agent side) allocates memory for each event (event is any action, # like RPC, telemetry, ...) and put in queue and wait feedback from the agent. @@ -612,100 +543,127 @@ B838E55D9366945FE643B14028366303 # This one frees the allocated fields and the event itself. # So the all issues related with sdk when a event is enqued is a false positive # 8 issues 8 type of events (so it matches) -# [067C59367AD524EC4D6133BE4D62A0AC : high : Memory Leak : controlflow ] -# -# sdk.c(244) : Branch taken: (h != NULL) -# sdk.c(244) : Branch taken: (h->exiting == 0) -# sdk.c(255) : Branch not taken: (event == NULL) -# sdk.c(259) : start -> allocated : config = xcalloc_internal(...) -# util.c(188) : start -> allocated : vp = calloc(...) -# util.c(188) : allocated -> allocated : vp refers to dynamically allocated memory -# util.c(189) : Branch not taken: (vp != NULL) -# util.c(192) : allocated -> allocated : return -# sdk.c(259) : allocated -> allocated : config refers to dynamically allocated memory -# sdk.c(267) : allocated -> allocated : config no longer refers to dynamically allocated memory -# sdk.c(267) : allocated -> leak : config end scope : Memory leaked -067C59367AD524EC4D6133BE4D62A0AC - -# [DCAD7EB558B6D37BA468C58E7B1385D7 : high : Memory Leak : controlflow ] -# -# sdk.c(301) : Branch taken: (h != NULL) -# sdk.c(301) : Branch taken: (h->exiting == 0) -# sdk.c(302) : start -> allocated : r = xcalloc_internal(...) -# util.c(188) : start -> allocated : vp = calloc(...) -# util.c(188) : allocated -> allocated : vp refers to dynamically allocated memory -# util.c(189) : Branch not taken: (vp != NULL) -# util.c(192) : allocated -> allocated : return -# sdk.c(302) : allocated -> allocated : r refers to dynamically allocated memory -# sdk.c(309) : allocated -> allocated : r no longer refers to dynamically allocated memory -# sdk.c(309) : allocated -> leak : r end scope : Memory leaked -DCAD7EB558B6D37BA468C58E7B1385D7 - -# [0225114F0DD658B78203F1590A4D491A : high : Memory Leak : controlflow ] -# -# sdk.c(244) : Branch taken: (h != NULL) -# sdk.c(244) : Branch taken: (h->exiting == 0) -# sdk.c(264) : start -> allocated : config->topic = xstrdup_internal(...) -# util.c(221) : start -> allocated : cp = strdup(...) -# util.c(221) : allocated -> allocated : cp refers to dynamically allocated memory -# util.c(222) : Branch not taken: (cp != NULL) -# util.c(225) : allocated -> allocated : return -# sdk.c(264) : allocated -> allocated : config->topic refers to dynamically allocated memory -# sdk.c(267) : allocated -> allocated : config->topic no longer refers to dynamically allocated memory -# sdk.c(267) : allocated -> leak : config end scope : Memory leaked -0225114F0DD658B78203F1590A4D491A +#[753C80AA0C46D7EFF76F1EF35D45EAA6 : high : Memory Leak : controlflow ] +# +# sdk.c(245) : Branch taken: (h != NULL) +# sdk.c(245) : Branch taken: (h->exiting == 0) +# sdk.c(256) : Branch not taken: (event == NULL) +# sdk.c(260) : start -> allocated : config = xcalloc_internal(...) +# util.c(188) : start -> allocated : vp = calloc(...) +# util.c(188) : allocated -> allocated : vp refers to dynamically allocated memory +# util.c(189) : Branch not taken: (vp != NULL) +# util.c(192) : allocated -> allocated : return +# sdk.c(260) : allocated -> allocated : config refers to dynamically allocated memory +# sdk.c(268) : allocated -> allocated : config no longer refers to dynamically allocated memory +# sdk.c(268) : allocated -> leak : config end scope : Memory leaked +753C80AA0C46D7EFF76F1EF35D45EAA6 + +#[7E30001FB07717CFF2FE5B13587B01B0 : high : Memory Leak : controlflow ] +# +# sdk.c(302) : Branch taken: (h != NULL) +# sdk.c(302) : Branch taken: (h->exiting == 0) +# sdk.c(303) : start -> allocated : r = xcalloc_internal(...) +# util.c(188) : start -> allocated : vp = calloc(...) +# util.c(188) : allocated -> allocated : vp refers to dynamically allocated memory +# util.c(189) : Branch not taken: (vp != NULL) +# util.c(192) : allocated -> allocated : return +# sdk.c(303) : allocated -> allocated : r refers to dynamically allocated memory +# sdk.c(310) : allocated -> allocated : r no longer refers to dynamically allocated memory +# sdk.c(310) : allocated -> leak : r end scope : Memory leaked +7E30001FB07717CFF2FE5B13587B01B0 + +#[753C80AA0C46D7EFF76F1EF35D45EAA6 : high : Memory Leak : controlflow ] +# +# sdk.c(245) : Branch taken: (h != NULL) +# sdk.c(245) : Branch taken: (h->exiting == 0) +# sdk.c(256) : Branch not taken: (event == NULL) +# sdk.c(260) : start -> allocated : config = xcalloc_internal(...) +# util.c(188) : start -> allocated : vp = calloc(...) +# util.c(188) : allocated -> allocated : vp refers to dynamically allocated memory +# util.c(189) : Branch not taken: (vp != NULL) +# util.c(192) : allocated -> allocated : return +# sdk.c(260) : allocated -> allocated : config refers to dynamically allocated memory +# sdk.c(268) : allocated -> allocated : config no longer refers to dynamically allocated memory +# sdk.c(268) : allocated -> leak : config end scope : Memory leaked +753C80AA0C46D7EFF76F1EF35D45EAA6 # False positive. The ownership for instance_name is transferred to the # caller when successful. Otherwise, the memory is released via free(3). -# [2875963782EF8F6D3886C98861CEC80A : high : Memory Leak : controlflow ] -# -# sdk.c(1340) : start -> allocated : instance_name = strdup(...) -# sdk.c(1340) : allocated -> allocated : instance_name refers to dynamically allocated memory -# sdk.c(1343) : Branch not taken: (instance_name != NULL) -# sdk.c(1343) : Branch taken: (remote_name == NULL) -# sdk.c(1345) : goto -# sdk.c(1355) : Branch not taken: (ret == 0) -# sdk.c(1360) : allocated -> allocated : instance_name no longer refers to dynamically allocated memory -# sdk.c(1360) : allocated -> leak : instance_name end scope : Memory leaked -2875963782EF8F6D3886C98861CEC80A +#[BC68A3AE07F66F3EA7F344AA1CF6B9E1 : high : Memory Leak : controlflow ] +# +# sdk.c(1351) : start -> allocated : instance_name = strdup(...) +# sdk.c(1351) : allocated -> allocated : instance_name refers to dynamically allocated memory +# sdk.c(1353) : Branch taken: (evp_ext->storage_name != NULL) +# sdk.c(1356) : Branch taken: (storage_name == NULL) +# sdk.c(1358) : goto +# sdk.c(1372) : Branch not taken: (ret == 0) +# sdk.c(1377) : allocated -> allocated : instance_name no longer refers to dynamically allocated memory +# sdk.c(1377) : allocated -> leak : instance_name end scope : Memory leaked +BC68A3AE07F66F3EA7F344AA1CF6B9E1 -# False positive. Similar to 2875963782EF8F6D3886C98861CEC80A. -# [3D0F88E4D11DF8FC1CE7FBEA5FDCA9FC : high : Memory Leak : controlflow ] +# False positive. +#[88FACBFC4F408F7012D2315A7D788BF9 : high : Memory Leak : controlflow ] # -# sdk.c(1341) : start -> allocated : remote_name = strdup(...) -# sdk.c(1341) : allocated -> allocated : remote_name refers to dynamically allocated memory -# sdk.c(1343) : Branch taken: (instance_name == NULL) -# sdk.c(1345) : goto -# sdk.c(1355) : Branch not taken: (ret == 0) -# sdk.c(1360) : allocated -> allocated : remote_name no longer refers to dynamically allocated memory -# sdk.c(1360) : allocated -> leak : remote_name end scope : Memory leaked -3D0F88E4D11DF8FC1CE7FBEA5FDCA9FC - -# False positive. Similar to 2875963782EF8F6D3886C98861CEC80A. -# [00327D8809D0B8577E45D1A736AD8420 : high : Memory Leak : controlflow ] -# -# sdk.c(1370) : start -> allocated : remote_name = strdup(...) -# sdk.c(1370) : allocated -> allocated : remote_name refers to dynamically allocated memory -# sdk.c(1373) : Branch taken: (evp_ext->storage_name != NULL) -# sdk.c(1376) : Branch taken: (storage_name == NULL) -# sdk.c(1378) : goto -# sdk.c(1392) : Branch not taken: (ret == 0) -# sdk.c(1397) : allocated -> allocated : remote_name no longer refers to dynamically allocated memory -# sdk.c(1397) : allocated -> leak : remote_name end scope : Memory leaked -00327D8809D0B8577E45D1A736AD8420 +# sdk.c(1321) : start -> allocated : remote_name = strdup(...) +# sdk.c(1321) : allocated -> allocated : remote_name refers to dynamically allocated memory +# sdk.c(1323) : Branch taken: (instance_name == NULL) +# sdk.c(1325) : goto +# sdk.c(1335) : Branch not taken: (ret == 0) +# sdk.c(1340) : allocated -> allocated : remote_name no longer refers to dynamically allocated memory +# sdk.c(1340) : allocated -> leak : remote_name end scope : Memory leaked +88FACBFC4F408F7012D2315A7D788BF9 # False positive. Similar to 2875963782EF8F6D3886C98861CEC80A. -# [3CA40910073FFCA06B9FA2F3D81DA617 : high : Memory Leak : controlflow ] -# -# sdk.c(1371) : start -> allocated : instance_name = strdup(...) -# sdk.c(1371) : allocated -> allocated : instance_name refers to dynamically allocated memory -# sdk.c(1373) : Branch taken: (evp_ext->storage_name != NULL) -# sdk.c(1376) : Branch taken: (storage_name == NULL) -# sdk.c(1378) : goto -# sdk.c(1392) : Branch not taken: (ret == 0) -# sdk.c(1397) : allocated -> allocated : instance_name no longer refers to dynamically allocated memory -# sdk.c(1397) : allocated -> leak : instance_name end scope : Memory leaked -3CA40910073FFCA06B9FA2F3D81DA617 +#[05D749459E2661F49E9A2800A98323B3 : high : Memory Leak : controlflow ] +# +# sdk.c(1350) : start -> allocated : remote_name = strdup(...) +# sdk.c(1350) : allocated -> allocated : remote_name refers to dynamically allocated memory +# sdk.c(1353) : Branch taken: (evp_ext->storage_name != NULL) +# sdk.c(1356) : Branch taken: (storage_name == NULL) +# sdk.c(1358) : goto +# sdk.c(1372) : Branch not taken: (ret == 0) +# sdk.c(1377) : allocated -> allocated : remote_name no longer refers to dynamically allocated memory +# sdk.c(1377) : allocated -> leak : remote_name end scope : Memory leaked +05D749459E2661F49E9A2800A98323B3 + +#[13DD2A203C18A517C7B4840513317DB0 : high : Memory Leak : controlflow ] +# +# sdk.c(245) : Branch taken: (h != NULL) +# sdk.c(245) : Branch taken: (h->exiting == 0) +# sdk.c(265) : start -> allocated : config->topic = xstrdup_internal(...) +# util.c(221) : start -> allocated : cp = strdup(...) +# util.c(221) : allocated -> allocated : cp refers to dynamically allocated memory +# util.c(222) : Branch not taken: (cp != NULL) +# util.c(225) : allocated -> allocated : return +# sdk.c(265) : allocated -> allocated : config->topic refers to dynamically allocated memory +# sdk.c(268) : allocated -> allocated : config->topic no longer refers to dynamically allocated memory +# sdk.c(268) : allocated -> leak : config end scope : Memory leaked +13DD2A203C18A517C7B4840513317DB0 + +#[89E9B42F5C5AF6377B59C48DE9E785F7 : high : Memory Leak : controlflow ] +# +# sdk.c(1016) : Branch not taken: (g_mqtt_client != NULL) +# sdk.c(1022) : Branch not taken: (xmqtt_request_fits(g_mqtt_client, len) != 0) +# sdk.c(1033) : start -> allocated : state = malloc(...) +# sdk.c(1033) : allocated -> allocated : state refers to dynamically allocated memory +# sdk.c(1034) : Branch not taken: (state != NULL) +# sdk.c(1054) : Branch not taken: (oevent == NULL) +# sdk.c(1082) : Branch not taken: (ret == 0) +# sdk.c(1085) : allocated -> allocated : state no longer refers to dynamically allocated memory +# sdk.c(1085) : allocated -> leak : state end scope : Memory leaked +89E9B42F5C5AF6377B59C48DE9E785F7 + +#[4E89E0F5591AA8A38639E4FE6EB0A8B2 : high : Memory Leak : controlflow ] +# +# sdk.c(1320) : start -> allocated : instance_name = strdup(...) +# sdk.c(1320) : allocated -> allocated : instance_name refers to dynamically allocated memory +# sdk.c(1323) : Branch not taken: (instance_name != NULL) +# sdk.c(1323) : Branch taken: (remote_name == NULL) +# sdk.c(1325) : goto +# sdk.c(1335) : Branch not taken: (ret == 0) +# sdk.c(1340) : allocated -> allocated : instance_name no longer refers to dynamically allocated memory +# sdk.c(1340) : allocated -> leak : instance_name end scope : Memory leaked +4E89E0F5591AA8A38639E4FE6EB0A8B2 # False positive # @@ -718,14 +676,14 @@ DCAD7EB558B6D37BA468C58E7B1385D7 # gets each element in the queue # cast to specific event. # free at the end of each event by sdk_free_event -# [B0CE5CE3545B4A42DE7B936450EFBF70 : high : Memory Leak : controlflow ] +#[3E1476C1E6658229EE0E5AF63E7786B7 : high : Memory Leak : controlflow ] # -# sdk.c(1679) : start -> allocated : event_message = malloc(...) -# sdk.c(1679) : allocated -> allocated : event_message refers to dynamically allocated memory -# sdk.c(1681) : Branch not taken: (event_message != NULL) -# sdk.c(1712) : allocated -> allocated : event_message no longer refers to dynamically allocated memory -# sdk.c(1712) : allocated -> leak : event_message end scope : Memory leaked -B0CE5CE3545B4A42DE7B936450EFBF70 +# sdk.c(1659) : start -> allocated : event_message = malloc(...) +# sdk.c(1659) : allocated -> allocated : event_message refers to dynamically allocated memory +# sdk.c(1661) : Branch not taken: (event_message != NULL) +# sdk.c(1692) : allocated -> allocated : event_message no longer refers to dynamically allocated memory +# sdk.c(1692) : allocated -> leak : event_message end scope : Memory leaked +3E1476C1E6658229EE0E5AF63E7786B7 # False positive (idem of previous) # @@ -738,28 +696,28 @@ B0CE5CE3545B4A42DE7B936450EFBF70 # gets each element in the queue # cast to specific event. # free at the end of each event by sdk_free_event -# [7E018F765E3B9D243BFD58974619AB3E : high : Memory Leak : controlflow ] -# -# sdk.c(1741) : Branch not taken: (g_mqtt_client != NULL) -# sdk.c(1745) : Branch not taken: (xmqtt_request_fits(g_mqtt_client, total_size) != 0) -# sdk.c(1749) : start -> allocated : t = malloc(...) -# sdk.c(1749) : allocated -> allocated : t refers to dynamically allocated memory -# sdk.c(1750) : Branch not taken: (t != NULL) -# sdk.c(1780) : allocated -> allocated : t no longer refers to dynamically allocated memory -# sdk.c(1780) : allocated -> leak : t end scope : Memory leaked -7E018F765E3B9D243BFD58974619AB3E - -# [508BA8845299DD5DDF222FB8FABDB985 : high : Memory Leak : controlflow ] -# -# sdk.c(1837) : Branch not taken: (response != NULL) -# sdk.c(1846) : Branch not taken: (g_mqtt_client != NULL) -# sdk.c(1851) : Branch not taken: (xmqtt_request_fits(g_mqtt_client, outsz) != 0) -# sdk.c(1855) : start -> allocated : r = malloc(...) -# sdk.c(1855) : allocated -> allocated : r refers to dynamically allocated memory -# sdk.c(1856) : Branch not taken: (r != NULL) -# sdk.c(1884) : allocated -> allocated : r no longer refers to dynamically allocated memory -# sdk.c(1884) : allocated -> leak : r end scope : Memory leaked -508BA8845299DD5DDF222FB8FABDB985 +#[B3B20F3988D18CC8CA5C28514719C705 : high : Memory Leak : controlflow ] +# +# sdk.c(1721) : Branch not taken: (g_mqtt_client != NULL) +# sdk.c(1725) : Branch not taken: (xmqtt_request_fits(g_mqtt_client, total_size) != 0) +# sdk.c(1729) : start -> allocated : t = malloc(...) +# sdk.c(1729) : allocated -> allocated : t refers to dynamically allocated memory +# sdk.c(1730) : Branch not taken: (t != NULL) +# sdk.c(1760) : allocated -> allocated : t no longer refers to dynamically allocated memory +# sdk.c(1760) : allocated -> leak : t end scope : Memory leaked +B3B20F3988D18CC8CA5C28514719C705 + +#[D0731D514166A49C8FFB53F1F9FD92A2 : high : Memory Leak : controlflow ] +# +# sdk.c(1817) : Branch not taken: (response != NULL) +# sdk.c(1826) : Branch not taken: (g_mqtt_client != NULL) +# sdk.c(1831) : Branch not taken: (xmqtt_request_fits(g_mqtt_client, outsz) != 0) +# sdk.c(1835) : start -> allocated : r = malloc(...) +# sdk.c(1835) : allocated -> allocated : r refers to dynamically allocated memory +# sdk.c(1836) : Branch not taken: (r != NULL) +# sdk.c(1864) : allocated -> allocated : r no longer refers to dynamically allocated memory +# sdk.c(1864) : allocated -> leak : r end scope : Memory leaked +D0731D514166A49C8FFB53F1F9FD92A2 # It is true response might not be a null-terminated string, as it is # read from user input. However, this same assumption is made in a few @@ -788,15 +746,15 @@ B0CE5CE3545B4A42DE7B936450EFBF70 # False positive. # s.name is transferred to stream when the function is succesful. # Otherwise, it is freed via free_stream. -# [7DD7E3EDFC6A656A6A38B155B81127FB : high : Memory Leak : controlflow ] +# [0A6344F4769EBC172A111620056A0739 : high : Memory Leak : controlflow ] # -# libevp-agent/manifest.c(597) : start -> allocated : s.name = strdup(...) -# libevp-agent/manifest.c(597) : allocated -> allocated : s.name refers to dynamically allocated memory -# libevp-agent/manifest.c(599) : Branch not taken: (s.name != NULL) -# libevp-agent/manifest.c(607) : goto -# libevp-agent/manifest.c(644) : allocated -> allocated : s.name no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(644) : allocated -> leak : s end scope : Memory leaked -7DD7E3EDFC6A656A6A38B155B81127FB +# manifest.c(465) : start -> allocated : s.name = strdup(...) +# manifest.c(465) : allocated -> allocated : s.name refers to dynamically allocated memory +# manifest.c(467) : Branch not taken: (s.name != NULL) +# manifest.c(475) : goto +# manifest.c(507) : allocated -> allocated : s.name no longer refers to dynamically allocated memory +# manifest.c(507) : allocated -> leak : s end scope : Memory leaked +0A6344F4769EBC172A111620056A0739 # False positive. # namedup is transferred to a compound literal, which is then @@ -826,22 +784,6 @@ B0CE5CE3545B4A42DE7B936450EFBF70 # libevp-agent/stream/stream.c(543) : allocated -> leak : namedup end scope : Memory leaked E5BAF7C295BEB651FD2DBB5177CAC5CF -# False positive. Similar to E5BAF7C295BEB651FD2DBB5177CAC5CF. -# [26FAD77FB5A912E51915B0447E01950B : high : Memory Leak : controlflow ] -# -# libevp-agent/stream/stream.c(476) : Branch not taken: (namedup != NULL) -# libevp-agent/stream/stream.c(486) : Branch taken: (src->type == 1) -# libevp-agent/stream/stream.c(486) : goto -# libevp-agent/stream/stream.c(490) : start -> allocated : connectiondup = strdup(...) -# libevp-agent/stream/stream.c(490) : allocated -> allocated : connectiondup refers to dynamically allocated memory -# libevp-agent/stream/stream.c(491) : Branch not taken: (connectiondup != NULL) -# libevp-agent/stream/stream.c(498) : allocated -> allocated : connectiondup refers to dynamically allocated memory -# libevp-agent/stream/stream.c(503) : allocated -> allocated : connectiondup no longer refers to dynamically allocated memory -# libevp-agent/stream/stream.c(538) : Branch not taken: (ret == 0) -# libevp-agent/stream/stream.c(543) : allocated -> allocated : connectiondup no longer refers to dynamically allocated memory -# libevp-agent/stream/stream.c(543) : allocated -> leak : connectiondup end scope : Memory leaked -26FAD77FB5A912E51915B0447E01950B - # False positive. # list is transferred to *dst if successful. Otherwise, it is free(3)d. # [124499A2BD2494F9F09B48FD37DABF50 : high : Memory Leak : controlflow ] @@ -886,16 +828,16 @@ EC095B6EAD3150351E9E6E34CE065126 # False positive. # Fortify fails to see sem is a semaphore that would block until # the event is handled (and free(3)d) by the module instance thread. -# [8BA0A1D5D111E79758AE1C485172AF1F : high : Memory Leak : controlflow ] +#[16C3E81F20D2E967B9D97592D8968F69 : high : Memory Leak : controlflow ] # -# sdk.c(1119) : Branch not taken: (sem_init((&sem), 0, 0) == 0) -# sdk.c(1126) : Branch taken: (h->exiting == 0) -# sdk.c(1127) : start -> allocated : event = malloc(...) -# sdk.c(1127) : allocated -> allocated : event refers to dynamically allocated memory -# sdk.c(1129) : Branch not taken: (event != NULL) -# sdk.c(1153) : allocated -> allocated : event no longer refers to dynamically allocated memory -# sdk.c(1153) : allocated -> leak : event end scope : Memory leaked -8BA0A1D5D111E79758AE1C485172AF1F +# sdk.c(1099) : Branch not taken: (sem_init((&sem), 0, 0) == 0) +# sdk.c(1106) : Branch taken: (h->exiting == 0) +# sdk.c(1107) : start -> allocated : event = malloc(...) +# sdk.c(1107) : allocated -> allocated : event refers to dynamically allocated memory +# sdk.c(1109) : Branch not taken: (event != NULL) +# sdk.c(1133) : allocated -> allocated : event no longer refers to dynamically allocated memory +# sdk.c(1133) : allocated -> leak : event end scope : Memory leaked +16C3E81F20D2E967B9D97592D8968F69 # IMPORTANT NOTE: This is an actual memory leak (!) # For implementations using sdk_local_wasm.c, response_copy is never freed. @@ -1033,53 +975,34 @@ D5DDC692344473E0E239F218E33EF21D # - process_send_rpc_response (buf -> rawbuf) # - EVP_impl_sendRpcResponse assigns it to event # - The event is enqueued in the events queue (idem as above) -# [7B535B7E1D5134638028FCA6838736C8 : high : Memory Leak : controlflow ] -# -# libevp-agent/sdkrpc/server.c(56) : Branch not taken: (ssz != -1) -# libevp-agent/sdkrpc/server.c(59) : Branch not taken: (ssz >= 16) -# libevp-agent/sdkrpc/server.c(63) : Branch not taken: (hdr.zero == 0) -# libevp-agent/sdkrpc/server.c(69) : Branch not taken: (sz != 0) -# libevp-agent/sdkrpc/server.c(74) : Branch not taken: (sz <= 131072) -# libevp-agent/sdkrpc/server.c(84) : start -> allocated : buf = xcalloc_internal(...) -# libevp-agent/util.c(194) : start -> allocated : vp = calloc(...) -# libevp-agent/util.c(194) : allocated -> allocated : vp refers to dynamically allocated memory -# libevp-agent/util.c(195) : Branch not taken: (vp != NULL) -# libevp-agent/util.c(198) : allocated -> allocated : return -# libevp-agent/sdkrpc/server.c(84) : allocated -> allocated : buf refers to dynamically allocated memory -# libevp-agent/sdkrpc/server.c(86) : Branch not taken: (ssz != -1) -# libevp-agent/sdkrpc/server.c(89) : Branch not taken: (ssz >= sz) -# libevp-agent/sdkrpc/server.c(96) : allocated -> allocated : sdk_process_request(buf, ?, ?, ?) -# libevp-agent/sdk_remote.c(916) : allocated -> allocated : buf refers to dynamically allocated memory -# libevp-agent/sdk_remote.c(920) : Branch not taken: (ret == 0) -# libevp-agent/sdk_remote.c(929) : Branch taken: (h != NULL) -# libevp-agent/sdk_remote.c(931) : Branch taken: (req != NULL) -# libevp-agent/sdk_remote.c(941) : goto -# libevp-agent/sdk_remote.c(967) : Branch taken: (fn != NULL) -# libevp-agent/sdk_remote.c(970) : Branch not taken: (error == 0) -# libevp-agent/sdk_remote.c(975) : Branch taken: (resp->buf != NULL) -# libevp-agent/sdk_remote.c(977) : Branch taken: (resp->buflen > 0) -# libevp-agent/sdkrpc/server.c(97) : allocated -> allocated : buf no longer refers to dynamically allocated memory -# libevp-agent/sdkrpc/server.c(97) : allocated -> leak : buf end scope : Memory leaked -7B535B7E1D5134638028FCA6838736C8 - -# A false positive. -# The allocated object is attached to another object. -# [EFB49A2723D07EE736C615C0F79F438E : high : Memory Leak : controlflow ] -# -# sdk.c(1010) : Branch not taken: (iret == 0) -# sdk.c(1017) : Branch not taken: (v != NULL) -# sdk.c(1022) : Branch not taken: (o != NULL) -# sdk.c(1026) : Branch not taken: (json_object_set_string(o, name, base64) == 0) -# sdk.c(1033) : Branch not taken: (g_mqtt_client != NULL) -# sdk.c(1039) : Branch not taken: (xmqtt_request_fits(g_mqtt_client, len) != 0) -# sdk.c(1050) : start -> allocated : state = malloc(...) -# sdk.c(1050) : allocated -> allocated : state refers to dynamically allocated memory -# sdk.c(1051) : Branch not taken: (state != NULL) -# sdk.c(1071) : Branch not taken: (oevent == NULL) -# sdk.c(1102) : Branch not taken: (ret == 0) -# sdk.c(1105) : allocated -> allocated : state no longer refers to dynamically allocated memory -# sdk.c(1105) : allocated -> leak : state end scope : Memory leaked -EFB49A2723D07EE736C615C0F79F438E +# [9AD20D74459F476EC44B35052092111A : high : Memory Leak : controlflow ] +# +# sdkrpc/server.c(51) : Branch not taken: (ssz >= 0) +# sdkrpc/server.c(54) : Branch not taken: (ssz >= 16) +# sdkrpc/server.c(58) : Branch not taken: (hdr.zero == 0) +# sdkrpc/server.c(64) : Branch not taken: (sz != 0) +# sdkrpc/server.c(69) : Branch not taken: (sz <= 131072) +# sdkrpc/server.c(84) : start -> allocated : buf = xcalloc_internal(...) +# util.c(188) : start -> allocated : vp = calloc(...) +# util.c(188) : allocated -> allocated : vp refers to dynamically allocated memory +# util.c(189) : Branch not taken: (vp != NULL) +# util.c(192) : allocated -> allocated : return +# sdkrpc/server.c(84) : allocated -> allocated : buf refers to dynamically allocated memory +# sdkrpc/server.c(86) : Branch not taken: (ssz >= 0) +# sdkrpc/server.c(89) : Branch not taken: (ssz >= sz) +# sdkrpc/server.c(96) : allocated -> allocated : sdk_process_request(buf, ?, ?, ?) +# sdk_remote.c(899) : allocated -> allocated : buf refers to dynamically allocated memory +# sdk_remote.c(903) : Branch not taken: (ret == 0) +# sdk_remote.c(912) : Branch taken: (h != NULL) +# sdk_remote.c(914) : Branch taken: (req != NULL) +# sdk_remote.c(924) : goto +# sdk_remote.c(950) : Branch taken: (fn != NULL) +# sdk_remote.c(953) : Branch not taken: (error == 0) +# sdk_remote.c(958) : Branch taken: (resp->buf != NULL) +# sdk_remote.c(960) : Branch taken: (resp->buflen > 0) +# sdkrpc/server.c(97) : allocated -> allocated : buf no longer refers to dynamically allocated memory +# sdkrpc/server.c(97) : allocated -> leak : buf end scope : Memory leaked +9AD20D74459F476EC44B35052092111A # False positive. # Yet again, Fortify fails to see the ownership for eventdup is transferred @@ -1445,217 +1368,223 @@ C1AF649FEDEB4229BFC18C509C83E800 # False positive. # Fortify fails to see that, in case of failure, instance.entryPoint # is free(3)d by free_module_instance_spec. -# [A9783E58C961156441ACFD57F3739B4D : high : Memory Leak : controlflow ] -# -# libevp-agent/manifest.c(862) : Branch not taken: (v != NULL) -# libevp-agent/manifest.c(870) : Branch not taken: (o != NULL) -# libevp-agent/manifest.c(870) : Branch not taken: (moduleId != NULL) -# libevp-agent/manifest.c(871) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) -# libevp-agent/manifest.c(878) : Branch not taken: (entryPoint != NULL) -# libevp-agent/manifest.c(883) : start -> allocated : instance.entryPoint = strdup(...) -# libevp-agent/manifest.c(883) : allocated -> allocated : instance.entryPoint refers to dynamically allocated memory -# libevp-agent/manifest.c(885) : Branch not taken: (instance.entryPoint != NULL) -# libevp-agent/manifest.c(893) : Branch taken: (ret != 0) -# libevp-agent/manifest.c(896) : goto -# libevp-agent/manifest.c(938) : allocated -> allocated : instance.entryPoint no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(938) : allocated -> leak : instance end scope : Memory leaked -# -# libevp-agent/manifest.c(862) : Branch not taken: (v != NULL) -# libevp-agent/manifest.c(870) : Branch not taken: (o != NULL) -# libevp-agent/manifest.c(870) : Branch not taken: (moduleId != NULL) -# libevp-agent/manifest.c(871) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) -# libevp-agent/manifest.c(878) : Branch not taken: (entryPoint != NULL) -# libevp-agent/manifest.c(883) : start -> allocated : instance.entryPoint = strdup(...) -# libevp-agent/manifest.c(883) : allocated -> allocated : instance.entryPoint refers to dynamically allocated memory -# libevp-agent/manifest.c(885) : Branch not taken: (instance.entryPoint != NULL) -# libevp-agent/manifest.c(893) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(901) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(909) : Branch not taken: (instance.name != NULL) -# libevp-agent/manifest.c(917) : Branch not taken: (instance.moduleId != NULL) -# libevp-agent/manifest.c(929) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(934) : allocated -> allocated : return -# libevp-agent/manifest.c(934) : allocated -> allocated : instance.entryPoint no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(934) : allocated -> leak : instance end scope : Memory leaked -A9783E58C961156441ACFD57F3739B4D - -# False positive. Similar to A9783E58C961156441ACFD57F3739B4D. -# [02417191CBB22D04481F86C433D27E69 : high : Memory Leak : controlflow ] -# -# libevp-agent/manifest.c(862) : Branch not taken: (v != NULL) -# libevp-agent/manifest.c(870) : Branch not taken: (o != NULL) -# libevp-agent/manifest.c(870) : Branch not taken: (moduleId != NULL) -# libevp-agent/manifest.c(871) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) -# libevp-agent/manifest.c(878) : Branch not taken: (entryPoint != NULL) -# libevp-agent/manifest.c(885) : Branch not taken: (instance.entryPoint != NULL) -# libevp-agent/manifest.c(893) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(901) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(907) : start -> allocated : instance.name = strdup(...) -# libevp-agent/manifest.c(907) : allocated -> allocated : instance.name refers to dynamically allocated memory -# libevp-agent/manifest.c(909) : Branch not taken: (instance.name != NULL) -# libevp-agent/manifest.c(917) : Branch taken: (instance.moduleId == NULL) -# libevp-agent/manifest.c(920) : goto -# libevp-agent/manifest.c(938) : allocated -> allocated : instance.name no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(938) : allocated -> leak : instance end scope : Memory leaked -# -# libevp-agent/manifest.c(862) : Branch not taken: (v != NULL) -# libevp-agent/manifest.c(870) : Branch not taken: (o != NULL) -# libevp-agent/manifest.c(870) : Branch not taken: (moduleId != NULL) -# libevp-agent/manifest.c(871) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) -# libevp-agent/manifest.c(878) : Branch not taken: (entryPoint != NULL) -# libevp-agent/manifest.c(885) : Branch not taken: (instance.entryPoint != NULL) -# libevp-agent/manifest.c(893) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(901) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(907) : start -> allocated : instance.name = strdup(...) -# libevp-agent/manifest.c(907) : allocated -> allocated : instance.name refers to dynamically allocated memory -# libevp-agent/manifest.c(909) : Branch not taken: (instance.name != NULL) -# libevp-agent/manifest.c(917) : Branch not taken: (instance.moduleId != NULL) -# libevp-agent/manifest.c(929) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(934) : allocated -> allocated : return -# libevp-agent/manifest.c(934) : allocated -> allocated : instance.name no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(934) : allocated -> leak : instance end scope : Memory leaked -02417191CBB22D04481F86C433D27E69 - -# False positive. Similar to A9783E58C961156441ACFD57F3739B4D. -# [345E5BE7C1620FD439159C04DC190011 : high : Memory Leak : controlflow ] -# -# libevp-agent/manifest.c(862) : Branch not taken: (v != NULL) -# libevp-agent/manifest.c(870) : Branch not taken: (o != NULL) -# libevp-agent/manifest.c(870) : Branch not taken: (moduleId != NULL) -# libevp-agent/manifest.c(871) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) -# libevp-agent/manifest.c(878) : Branch not taken: (entryPoint != NULL) -# libevp-agent/manifest.c(885) : Branch not taken: (instance.entryPoint != NULL) -# libevp-agent/manifest.c(893) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(901) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(909) : Branch not taken: (instance.name != NULL) -# libevp-agent/manifest.c(915) : start -> allocated : instance.moduleId = strdup(...) -# libevp-agent/manifest.c(915) : allocated -> allocated : instance.moduleId refers to dynamically allocated memory -# libevp-agent/manifest.c(917) : Branch not taken: (instance.moduleId != NULL) -# libevp-agent/manifest.c(929) : Branch taken: (ret != 0) -# libevp-agent/manifest.c(930) : goto -# libevp-agent/manifest.c(938) : allocated -> allocated : instance.moduleId no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(938) : allocated -> leak : instance end scope : Memory leaked -# -# libevp-agent/manifest.c(862) : Branch not taken: (v != NULL) -# libevp-agent/manifest.c(870) : Branch not taken: (o != NULL) -# libevp-agent/manifest.c(870) : Branch not taken: (moduleId != NULL) -# libevp-agent/manifest.c(871) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) -# libevp-agent/manifest.c(878) : Branch not taken: (entryPoint != NULL) -# libevp-agent/manifest.c(885) : Branch not taken: (instance.entryPoint != NULL) -# libevp-agent/manifest.c(893) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(901) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(909) : Branch not taken: (instance.name != NULL) -# libevp-agent/manifest.c(915) : start -> allocated : instance.moduleId = strdup(...) -# libevp-agent/manifest.c(915) : allocated -> allocated : instance.moduleId refers to dynamically allocated memory -# libevp-agent/manifest.c(917) : Branch not taken: (instance.moduleId != NULL) -# libevp-agent/manifest.c(929) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(934) : allocated -> allocated : return -# libevp-agent/manifest.c(934) : allocated -> allocated : instance.moduleId no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(934) : allocated -> leak : instance end scope : Memory leaked -345E5BE7C1620FD439159C04DC190011 - -# False positive. Similar to A9783E58C961156441ACFD57F3739B4D. -# [0AE3683072C00C18D5DBCD59A9D9911F : high : Memory Leak : controlflow ] -# -# libevp-agent/manifest.c(1053) : Branch not taken: (o != NULL) -# libevp-agent/manifest.c(1053) : Branch not taken: (moduleId != NULL) -# libevp-agent/manifest.c(1054) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) -# libevp-agent/manifest.c(1061) : Branch not taken: (entryPoint != NULL) -# libevp-agent/manifest.c(1066) : start -> allocated : instance.entryPoint = strdup(...) -# libevp-agent/manifest.c(1066) : allocated -> allocated : instance.entryPoint refers to dynamically allocated memory -# libevp-agent/manifest.c(1068) : Branch not taken: (instance.entryPoint != NULL) -# libevp-agent/manifest.c(1076) : Branch taken: (ret != 0) -# libevp-agent/manifest.c(1079) : goto -# libevp-agent/manifest.c(1132) : allocated -> allocated : instance.entryPoint no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(1132) : allocated -> leak : instance end scope : Memory leaked -# -# libevp-agent/manifest.c(1053) : Branch not taken: (o != NULL) -# libevp-agent/manifest.c(1053) : Branch not taken: (moduleId != NULL) -# libevp-agent/manifest.c(1054) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) -# libevp-agent/manifest.c(1061) : Branch not taken: (entryPoint != NULL) -# libevp-agent/manifest.c(1066) : start -> allocated : instance.entryPoint = strdup(...) -# libevp-agent/manifest.c(1066) : allocated -> allocated : instance.entryPoint refers to dynamically allocated memory -# libevp-agent/manifest.c(1068) : Branch not taken: (instance.entryPoint != NULL) -# libevp-agent/manifest.c(1076) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(1084) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(1092) : Branch not taken: (instance.name != NULL) -# libevp-agent/manifest.c(1100) : Branch not taken: (instance.moduleId != NULL) -# libevp-agent/manifest.c(1117) : Branch not taken: (streams == NULL) -# libevp-agent/manifest.c(1128) : allocated -> allocated : return -# libevp-agent/manifest.c(1128) : allocated -> allocated : instance.entryPoint no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(1128) : allocated -> leak : instance end scope : Memory leaked -0AE3683072C00C18D5DBCD59A9D9911F - -# False positive. Similar to A9783E58C961156441ACFD57F3739B4D. -# [9762EE270A23868FD534DA82DD8C7AEB : high : Memory Leak : controlflow ] -# -# libevp-agent/manifest.c(1053) : Branch not taken: (o != NULL) -# libevp-agent/manifest.c(1053) : Branch not taken: (moduleId != NULL) -# libevp-agent/manifest.c(1054) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) -# libevp-agent/manifest.c(1061) : Branch not taken: (entryPoint != NULL) -# libevp-agent/manifest.c(1068) : Branch not taken: (instance.entryPoint != NULL) -# libevp-agent/manifest.c(1076) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(1084) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(1090) : start -> allocated : instance.name = strdup(...) -# libevp-agent/manifest.c(1090) : allocated -> allocated : instance.name refers to dynamically allocated memory -# libevp-agent/manifest.c(1092) : Branch not taken: (instance.name != NULL) -# libevp-agent/manifest.c(1100) : Branch taken: (instance.moduleId == NULL) -# libevp-agent/manifest.c(1103) : goto -# libevp-agent/manifest.c(1132) : allocated -> allocated : instance.name no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(1132) : allocated -> leak : instance end scope : Memory leaked -# -# libevp-agent/manifest.c(1053) : Branch not taken: (o != NULL) -# libevp-agent/manifest.c(1053) : Branch not taken: (moduleId != NULL) -# libevp-agent/manifest.c(1054) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) -# libevp-agent/manifest.c(1061) : Branch not taken: (entryPoint != NULL) -# libevp-agent/manifest.c(1068) : Branch not taken: (instance.entryPoint != NULL) -# libevp-agent/manifest.c(1076) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(1084) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(1090) : start -> allocated : instance.name = strdup(...) -# libevp-agent/manifest.c(1090) : allocated -> allocated : instance.name refers to dynamically allocated memory -# libevp-agent/manifest.c(1092) : Branch not taken: (instance.name != NULL) -# libevp-agent/manifest.c(1100) : Branch not taken: (instance.moduleId != NULL) -# libevp-agent/manifest.c(1117) : Branch not taken: (streams == NULL) -# libevp-agent/manifest.c(1128) : allocated -> allocated : return -# libevp-agent/manifest.c(1128) : allocated -> allocated : instance.name no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(1128) : allocated -> leak : instance end scope : Memory leaked -9762EE270A23868FD534DA82DD8C7AEB - -# False positive. Similar to A9783E58C961156441ACFD57F3739B4D. -# [B32C402AEF8096D587CBE9E630A4BFD0 : high : Memory Leak : controlflow ] -# -# libevp-agent/manifest.c(1053) : Branch not taken: (o != NULL) -# libevp-agent/manifest.c(1053) : Branch not taken: (moduleId != NULL) -# libevp-agent/manifest.c(1054) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) -# libevp-agent/manifest.c(1061) : Branch not taken: (entryPoint != NULL) -# libevp-agent/manifest.c(1068) : Branch not taken: (instance.entryPoint != NULL) -# libevp-agent/manifest.c(1076) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(1084) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(1092) : Branch not taken: (instance.name != NULL) -# libevp-agent/manifest.c(1098) : start -> allocated : instance.moduleId = strdup(...) -# libevp-agent/manifest.c(1098) : allocated -> allocated : instance.moduleId refers to dynamically allocated memory -# libevp-agent/manifest.c(1100) : Branch not taken: (instance.moduleId != NULL) -# libevp-agent/manifest.c(1117) : Branch not taken: (streams == NULL) -# libevp-agent/manifest.c(1128) : allocated -> allocated : return -# libevp-agent/manifest.c(1128) : allocated -> allocated : instance.moduleId no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(1128) : allocated -> leak : instance end scope : Memory leaked -# -# libevp-agent/manifest.c(1053) : Branch not taken: (o != NULL) -# libevp-agent/manifest.c(1053) : Branch not taken: (moduleId != NULL) -# libevp-agent/manifest.c(1054) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) -# libevp-agent/manifest.c(1061) : Branch not taken: (entryPoint != NULL) -# libevp-agent/manifest.c(1068) : Branch not taken: (instance.entryPoint != NULL) -# libevp-agent/manifest.c(1076) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(1084) : Branch not taken: (ret == 0) -# libevp-agent/manifest.c(1092) : Branch not taken: (instance.name != NULL) -# libevp-agent/manifest.c(1098) : start -> allocated : instance.moduleId = strdup(...) -# libevp-agent/manifest.c(1098) : allocated -> allocated : instance.moduleId refers to dynamically allocated memory -# libevp-agent/manifest.c(1100) : Branch not taken: (instance.moduleId != NULL) -# libevp-agent/manifest.c(1117) : Branch taken: (streams != NULL) -# libevp-agent/manifest.c(1119) : Branch taken: (ret != 0) -# libevp-agent/manifest.c(1121) : goto -# libevp-agent/manifest.c(1132) : allocated -> allocated : instance.moduleId no longer refers to dynamically allocated memory -# libevp-agent/manifest.c(1132) : allocated -> leak : instance end scope : Memory leaked -B32C402AEF8096D587CBE9E630A4BFD0 +# [F99AECBB87090FBF69CAE4BB005C57E2 : high : Memory Leak : controlflow ] +# +# manifest.c(725) : Branch not taken: (v != NULL) +# manifest.c(733) : Branch not taken: (o != NULL) +# manifest.c(733) : Branch not taken: (moduleId != NULL) +# manifest.c(734) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) +# manifest.c(741) : Branch not taken: (entryPoint != NULL) +# manifest.c(746) : start -> allocated : instance.entryPoint = strdup(...) +# manifest.c(746) : allocated -> allocated : instance.entryPoint refers to dynamically allocated memory +# manifest.c(748) : Branch not taken: (instance.entryPoint != NULL) +# manifest.c(756) : Branch taken: (ret != 0) +# manifest.c(759) : goto +# manifest.c(801) : allocated -> allocated : instance.entryPoint no longer refers to dynamically allocated memory +# manifest.c(801) : allocated -> leak : instance end scope : Memory leaked +# +# manifest.c(725) : Branch not taken: (v != NULL) +# manifest.c(733) : Branch not taken: (o != NULL) +# manifest.c(733) : Branch not taken: (moduleId != NULL) +# manifest.c(734) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) +# manifest.c(741) : Branch not taken: (entryPoint != NULL) +# manifest.c(746) : start -> allocated : instance.entryPoint = strdup(...) +# manifest.c(746) : allocated -> allocated : instance.entryPoint refers to dynamically allocated memory +# manifest.c(748) : Branch not taken: (instance.entryPoint != NULL) +# manifest.c(756) : Branch not taken: (ret == 0) +# manifest.c(764) : Branch not taken: (ret == 0) +# manifest.c(772) : Branch not taken: (instance.name != NULL) +# manifest.c(780) : Branch not taken: (instance.moduleId != NULL) +# manifest.c(792) : Branch not taken: (ret == 0) +# manifest.c(797) : allocated -> allocated : return +# manifest.c(797) : allocated -> allocated : instance.entryPoint no longer refers to dynamically allocated memory +# manifest.c(797) : allocated -> leak : instance end scope : Memory leaked +F99AECBB87090FBF69CAE4BB005C57E2 + +# False positive. Similar to F99AECBB87090FBF69CAE4BB005C57E2. +# [79ED26DD8F3723080A20179B526D8E78 : high : Memory Leak : controlflow ] +# +# manifest.c(725) : Branch not taken: (v != NULL) +# manifest.c(733) : Branch not taken: (o != NULL) +# manifest.c(733) : Branch not taken: (moduleId != NULL) +# manifest.c(734) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) +# manifest.c(741) : Branch not taken: (entryPoint != NULL) +# manifest.c(748) : Branch not taken: (instance.entryPoint != NULL) +# manifest.c(756) : Branch not taken: (ret == 0) +# manifest.c(764) : Branch not taken: (ret == 0) +# manifest.c(770) : start -> allocated : instance.name = strdup(...) +# manifest.c(770) : allocated -> allocated : instance.name refers to dynamically allocated memory +# manifest.c(772) : Branch not taken: (instance.name != NULL) +# manifest.c(780) : Branch taken: (instance.moduleId == NULL) +# manifest.c(783) : goto +# manifest.c(801) : allocated -> allocated : instance.name no longer refers to dynamically allocated memory +# manifest.c(801) : allocated -> leak : instance end scope : Memory leaked +# +# manifest.c(725) : Branch not taken: (v != NULL) +# manifest.c(733) : Branch not taken: (o != NULL) +# manifest.c(733) : Branch not taken: (moduleId != NULL) +# manifest.c(734) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) +# manifest.c(741) : Branch not taken: (entryPoint != NULL) +# manifest.c(748) : Branch not taken: (instance.entryPoint != NULL) +# manifest.c(756) : Branch not taken: (ret == 0) +# manifest.c(764) : Branch not taken: (ret == 0) +# manifest.c(770) : start -> allocated : instance.name = strdup(...) +# manifest.c(770) : allocated -> allocated : instance.name refers to dynamically allocated memory +# manifest.c(772) : Branch not taken: (instance.name != NULL) +# manifest.c(780) : Branch not taken: (instance.moduleId != NULL) +# manifest.c(792) : Branch not taken: (ret == 0) +# manifest.c(797) : allocated -> allocated : return +# manifest.c(797) : allocated -> allocated : instance.name no longer refers to dynamically allocated memory +# manifest.c(797) : allocated -> leak : instance end scope : Memory leaked +79ED26DD8F3723080A20179B526D8E78 + +# False positive. Similar to F99AECBB87090FBF69CAE4BB005C57E2. +# [556B4D067C64D486F428850F49F2AFF1 : high : Memory Leak : controlflow ] +# +# manifest.c(725) : Branch not taken: (v != NULL) +# manifest.c(733) : Branch not taken: (o != NULL) +# manifest.c(733) : Branch not taken: (moduleId != NULL) +# manifest.c(734) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) +# manifest.c(741) : Branch not taken: (entryPoint != NULL) +# manifest.c(748) : Branch not taken: (instance.entryPoint != NULL) +# manifest.c(756) : Branch not taken: (ret == 0) +# manifest.c(764) : Branch not taken: (ret == 0) +# manifest.c(772) : Branch not taken: (instance.name != NULL) +# manifest.c(778) : start -> allocated : instance.moduleId = strdup(...) +# manifest.c(778) : allocated -> allocated : instance.moduleId refers to dynamically allocated memory +# manifest.c(780) : Branch not taken: (instance.moduleId != NULL) +# manifest.c(792) : Branch taken: (ret != 0) +# manifest.c(793) : goto +# manifest.c(801) : allocated -> allocated : instance.moduleId no longer refers to dynamically allocated memory +# manifest.c(801) : allocated -> leak : instance end scope : Memory leaked +# +# manifest.c(725) : Branch not taken: (v != NULL) +# manifest.c(733) : Branch not taken: (o != NULL) +# manifest.c(733) : Branch not taken: (moduleId != NULL) +# manifest.c(734) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) +# manifest.c(741) : Branch not taken: (entryPoint != NULL) +# manifest.c(748) : Branch not taken: (instance.entryPoint != NULL) +# manifest.c(756) : Branch not taken: (ret == 0) +# manifest.c(764) : Branch not taken: (ret == 0) +# manifest.c(772) : Branch not taken: (instance.name != NULL) +# manifest.c(778) : start -> allocated : instance.moduleId = strdup(...) +# manifest.c(778) : allocated -> allocated : instance.moduleId refers to dynamically allocated memory +# manifest.c(780) : Branch not taken: (instance.moduleId != NULL) +# manifest.c(792) : Branch not taken: (ret == 0) +# manifest.c(797) : allocated -> allocated : return +# manifest.c(797) : allocated -> allocated : instance.moduleId no longer refers to dynamically allocated memory +# manifest.c(797) : allocated -> leak : instance end scope : Memory leaked +556B4D067C64D486F428850F49F2AFF1 + +# False positive. Similar to F99AECBB87090FBF69CAE4BB005C57E2. +# [F6C075848518BB810DD22EA06389658F : high : Memory Leak : controlflow ] +# +# manifest.c(916) : Branch not taken: (o != NULL) +# manifest.c(916) : Branch not taken: (moduleId != NULL) +# manifest.c(917) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) +# manifest.c(924) : Branch not taken: (entryPoint != NULL) +# manifest.c(929) : Branch not taken: (strlen(entryPoint) != 0) +# manifest.c(936) : start -> allocated : instance.entryPoint = strdup(...) +# manifest.c(936) : allocated -> allocated : instance.entryPoint refers to dynamically allocated memory +# manifest.c(938) : Branch not taken: (instance.entryPoint != NULL) +# manifest.c(946) : Branch taken: (ret != 0) +# manifest.c(949) : goto +# manifest.c(1002) : allocated -> allocated : instance.entryPoint no longer refers to dynamically allocated memory +# manifest.c(1002) : allocated -> leak : instance end scope : Memory leaked +# +# manifest.c(916) : Branch not taken: (o != NULL) +# manifest.c(916) : Branch not taken: (moduleId != NULL) +# manifest.c(917) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) +# manifest.c(924) : Branch not taken: (entryPoint != NULL) +# manifest.c(929) : Branch not taken: (strlen(entryPoint) != 0) +# manifest.c(936) : start -> allocated : instance.entryPoint = strdup(...) +# manifest.c(936) : allocated -> allocated : instance.entryPoint refers to dynamically allocated memory +# manifest.c(938) : Branch not taken: (instance.entryPoint != NULL) +# manifest.c(946) : Branch not taken: (ret == 0) +# manifest.c(954) : Branch not taken: (ret == 0) +# manifest.c(962) : Branch not taken: (instance.name != NULL) +# manifest.c(970) : Branch not taken: (instance.moduleId != NULL) +# manifest.c(987) : Branch not taken: (streams == NULL) +# manifest.c(998) : allocated -> allocated : return +# manifest.c(998) : allocated -> allocated : instance.entryPoint no longer refers to dynamically allocated memory +# manifest.c(998) : allocated -> leak : instance end scope : Memory leaked +F6C075848518BB810DD22EA06389658F + +# False positive. Similar to F99AECBB87090FBF69CAE4BB005C57E2. +# [00C342C2029E138DA2C4C403DD0136D4 : high : Memory Leak : controlflow ] +# +# manifest.c(916) : Branch not taken: (o != NULL) +# manifest.c(916) : Branch not taken: (moduleId != NULL) +# manifest.c(917) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) +# manifest.c(924) : Branch not taken: (entryPoint != NULL) +# manifest.c(929) : Branch not taken: (strlen(entryPoint) != 0) +# manifest.c(938) : Branch not taken: (instance.entryPoint != NULL) +# manifest.c(946) : Branch not taken: (ret == 0) +# manifest.c(954) : Branch not taken: (ret == 0) +# manifest.c(960) : start -> allocated : instance.name = strdup(...) +# manifest.c(960) : allocated -> allocated : instance.name refers to dynamically allocated memory +# manifest.c(962) : Branch not taken: (instance.name != NULL) +# manifest.c(970) : Branch taken: (instance.moduleId == NULL) +# manifest.c(973) : goto +# manifest.c(1002) : allocated -> allocated : instance.name no longer refers to dynamically allocated memory +# manifest.c(1002) : allocated -> leak : instance end scope : Memory leaked +# +# manifest.c(916) : Branch not taken: (o != NULL) +# manifest.c(916) : Branch not taken: (moduleId != NULL) +# manifest.c(917) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) +# manifest.c(924) : Branch not taken: (entryPoint != NULL) +# manifest.c(929) : Branch not taken: (strlen(entryPoint) != 0) +# manifest.c(938) : Branch not taken: (instance.entryPoint != NULL) +# manifest.c(946) : Branch not taken: (ret == 0) +# manifest.c(954) : Branch not taken: (ret == 0) +# manifest.c(960) : start -> allocated : instance.name = strdup(...) +# manifest.c(960) : allocated -> allocated : instance.name refers to dynamically allocated memory +# manifest.c(962) : Branch not taken: (instance.name != NULL) +# manifest.c(970) : Branch not taken: (instance.moduleId != NULL) +# manifest.c(987) : Branch not taken: (streams == NULL) +# manifest.c(998) : allocated -> allocated : return +# manifest.c(998) : allocated -> allocated : instance.name no longer refers to dynamically allocated memory +# manifest.c(998) : allocated -> leak : instance end scope : Memory leaked +00C342C2029E138DA2C4C403DD0136D4 + +# False positive. Similar to F99AECBB87090FBF69CAE4BB005C57E2. +# [1CE832BFD1FAEC22F58A5C5030F0E9C8 : high : Memory Leak : controlflow ] +# +# manifest.c(916) : Branch not taken: (o != NULL) +# manifest.c(916) : Branch not taken: (moduleId != NULL) +# manifest.c(917) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) +# manifest.c(924) : Branch not taken: (entryPoint != NULL) +# manifest.c(929) : Branch not taken: (strlen(entryPoint) != 0) +# manifest.c(938) : Branch not taken: (instance.entryPoint != NULL) +# manifest.c(946) : Branch not taken: (ret == 0) +# manifest.c(954) : Branch not taken: (ret == 0) +# manifest.c(962) : Branch not taken: (instance.name != NULL) +# manifest.c(968) : start -> allocated : instance.moduleId = strdup(...) +# manifest.c(968) : allocated -> allocated : instance.moduleId refers to dynamically allocated memory +# manifest.c(970) : Branch not taken: (instance.moduleId != NULL) +# manifest.c(987) : Branch not taken: (streams == NULL) +# manifest.c(998) : allocated -> allocated : return +# manifest.c(998) : allocated -> allocated : instance.moduleId no longer refers to dynamically allocated memory +# manifest.c(998) : allocated -> leak : instance end scope : Memory leaked +# +# manifest.c(916) : Branch not taken: (o != NULL) +# manifest.c(916) : Branch not taken: (moduleId != NULL) +# manifest.c(917) : Branch not taken: (strncmp(name, g_reserved_prefix, strlen(g_reserved_prefix)) != 0) +# manifest.c(924) : Branch not taken: (entryPoint != NULL) +# manifest.c(929) : Branch not taken: (strlen(entryPoint) != 0) +# manifest.c(938) : Branch not taken: (instance.entryPoint != NULL) +# manifest.c(946) : Branch not taken: (ret == 0) +# manifest.c(954) : Branch not taken: (ret == 0) +# manifest.c(962) : Branch not taken: (instance.name != NULL) +# manifest.c(968) : start -> allocated : instance.moduleId = strdup(...) +# manifest.c(968) : allocated -> allocated : instance.moduleId refers to dynamically allocated memory +# manifest.c(970) : Branch not taken: (instance.moduleId != NULL) +# manifest.c(987) : Branch taken: (streams != NULL) +# manifest.c(989) : Branch taken: (ret != 0) +# manifest.c(991) : goto +# manifest.c(1002) : allocated -> allocated : instance.moduleId no longer refers to dynamically allocated memory +# manifest.c(1002) : allocated -> leak : instance end scope : Memory leaked +1CE832BFD1FAEC22F58A5C5030F0E9C8 # False positive. # Yet again, Fortify fails to see the ownership for `topicdup` is transferred @@ -2748,52 +2677,50 @@ C382DF34B7262C9187069ABBC7FEEDCF # The string gets a final zero termination regardless, not counted in the # string length (in compliance with the FlatBuffers format)." -# [62B60C2E17194F11BC81E06AFE6A99F4 : high : String Termination Error : dataflow ] -# sdk.c(1076) : ->strcmp(1) -# sdk_remote.c(403) : ->EVP_impl_sendState(2) -# sdk_remote.c(397) : <=> (topic) -# sdkenc/sdk_reader.h(654) : return -# sdkenc/sdk_reader.h(654) : <=> (elem__tmp) -# sdk_remote.c(397) : <->EVP_SDK_StateInput_topic(0->return) -# sdk_remote.c(394) : <=> (state) -# sdkenc/sdk_reader.h(1104) : return -# sdkenc/sdk_reader.h(1104) : <=> (elem__tmp) -# sdk_remote.c(394) : <->EVP_SDK_Request_body(0->return) -# sdk_remote.c(982) : ->process_send_state(1) -# sdk_remote.c(939) : <=> (req) -# sdkenc/sdk_reader.h(1102) : return -# sdk_remote.c(939) : <->EVP_SDK_Request_as_root(0->return) -# sdkrpc/server.c(96) : ->sdk_process_request(0) -# sdkrpc/server.c(85) : <- readall(1) -# ioutil.c(22) : <- read(1) -# -# -# StateInput_topic is a Flatbuffer String. In sdkenc/sdk.fbs: +#[3397B3B424EF87DF712DEFD26B45C7AC : high : String Termination Error : dataflow ] +#sdk.c(1059) : ->strcmp(1) +# sdk_remote.c(403) : ->EVP_impl_sendState(2) +# sdk_remote.c(397) : <=> (topic) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(583) : return +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(583) : <=> (elem__tmp) +# sdk_remote.c(397) : <->EVP_SDK_StateInput_topic(0->return) +# sdk_remote.c(394) : <=> (state) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1033) : return +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1033) : <=> (elem__tmp) +# sdk_remote.c(394) : <->EVP_SDK_Request_body(0->return) +# sdk_remote.c(952) : ->process_send_state(1) +# sdk_remote.c(909) : <=> (req) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1031) : return +# sdk_remote.c(909) : <->EVP_SDK_Request_as_root(0->return) +# sdkrpc/server.c(96) : ->sdk_process_request(0) +# sdkrpc/server.c(85) : <- readall(1) +# ioutil.c(22) : <- read(1) +# +## StateInput_topic is a Flatbuffer String. In sdkenc/sdk.fbs: # table StateInput { # topic:string (required); -62B60C2E17194F11BC81E06AFE6A99F4 +3397B3B424EF87DF712DEFD26B45C7AC # StateInput_topic is a Flatbuffer String. In sdkenc/sdk.fbs: -#[CBC0774DF49EAD8C2B5A11C4FACD6362 : high : Format String : dataflow ] -#libevp-agent/util.c(294) : ->vasprintf(1) -# libevp-agent/sdk.c(987) : ->xasprintf_internal(5) -# libevp-agent/sdk_remote.c(386) : ->EVP_impl_sendState(2) -# libevp-agent/sdk_remote.c(380) : <=> (topic) -# libevp-agent/sdkenc/sdk_reader.h(648) : return -# libevp-agent/sdkenc/sdk_reader.h(648) : <=> (elem__tmp) -# libevp-agent/sdk_remote.c(380) : <->EVP_SDK_StateInput_topic(0->return) -# libevp-agent/sdk_remote.c(377) : <=> (state) -# libevp-agent/sdkenc/sdk_reader.h(1098) : return -# libevp-agent/sdkenc/sdk_reader.h(1098) : <=> (elem__tmp) -# libevp-agent/sdk_remote.c(377) : <->EVP_SDK_Request_body(0->return) -# libevp-agent/sdk_remote.c(914) : ->process_send_state(1) -# libevp-agent/sdk_remote.c(871) : <=> (req) -# libevp-agent/sdkenc/sdk_reader.h(1096) : return -# libevp-agent/sdk_remote.c(871) : <->EVP_SDK_Request_as_root(0->return) -# libevp-agent/sdkrpc/server.c(116) : ->sdk_process_request(0) -# libevp-agent/sdkrpc/server.c(105) : <- readall(1) -# libevp-agent/ioutil.c(28) : <- read(1) -CBC0774DF49EAD8C2B5A11C4FACD6362 +#[263E550BDAD8048B7714327862E5FA4B : high : String Termination Error : dataflow ] +#sdk.c(1008) : ->snprintf(4) +# sdk_remote.c(403) : ->EVP_impl_sendState(2) +# sdk_remote.c(397) : <=> (topic) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(583) : return +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(583) : <=> (elem__tmp) +# sdk_remote.c(397) : <->EVP_SDK_StateInput_topic(0->return) +# sdk_remote.c(394) : <=> (state) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1033) : return +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1033) : <=> (elem__tmp) +# sdk_remote.c(394) : <->EVP_SDK_Request_body(0->return) +# sdk_remote.c(952) : ->process_send_state(1) +# sdk_remote.c(909) : <=> (req) +# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1031) : return +# sdk_remote.c(909) : <->EVP_SDK_Request_as_root(0->return) +# sdkrpc/server.c(96) : ->sdk_process_request(0) +# sdkrpc/server.c(85) : <- readall(1) +# ioutil.c(22) : <- read(1) +263E550BDAD8048B7714327862E5FA4B # Seemingly false-positive # The buffer is big enough to store any possible values of uint16_t @@ -3247,20 +3174,20 @@ BA0F36F9B53D08073B3E0230D7DE21EB # False positive. # Yet again, Fortify fails to see the ownership for hostnamedup is transferred # to params.posix when the function is succesful. -# [E420D9DB4AAAEC85F8B479ADC95EDBF9 : high : Memory Leak : controlflow ] -# -# libevp-agent/stream/stream.c(476) : Branch not taken: (namedup != NULL) -# libevp-agent/stream/stream.c(505) : Branch taken: (src->type == 2) -# libevp-agent/stream/stream.c(505) : goto -# libevp-agent/stream/stream.c(509) : start -> allocated : hostnamedup = strdup(...) -# libevp-agent/stream/stream.c(509) : allocated -> allocated : hostnamedup refers to dynamically allocated memory -# libevp-agent/stream/stream.c(510) : Branch not taken: (hostnamedup != NULL) -# libevp-agent/stream/stream.c(519) : allocated -> allocated : hostnamedup refers to dynamically allocated memory -# libevp-agent/stream/stream.c(523) : allocated -> allocated : hostnamedup no longer refers to dynamically allocated memory -# libevp-agent/stream/stream.c(538) : Branch not taken: (ret == 0) -# libevp-agent/stream/stream.c(543) : allocated -> allocated : hostnamedup no longer refers to dynamically allocated memory -# libevp-agent/stream/stream.c(543) : allocated -> leak : hostnamedup end scope : Memory leaked -E420D9DB4AAAEC85F8B479ADC95EDBF9 +# [74169ED2AA3FB0795C28912A9E687D77 : high : Memory Leak : controlflow ] +# +# stream/stream.c(477) : Branch not taken: (namedup != NULL) +# stream/stream.c(487) : Branch taken: (src->type == 1) +# stream/stream.c(487) : goto +# stream/stream.c(491) : start -> allocated : hostnamedup = strdup(...) +# stream/stream.c(491) : allocated -> allocated : hostnamedup refers to dynamically allocated memory +# stream/stream.c(492) : Branch not taken: (hostnamedup != NULL) +# stream/stream.c(501) : allocated -> allocated : hostnamedup refers to dynamically allocated memory +# stream/stream.c(505) : allocated -> allocated : hostnamedup no longer refers to dynamically allocated memory +# stream/stream.c(520) : Branch not taken: (ret == 0) +# stream/stream.c(525) : allocated -> allocated : hostnamedup no longer refers to dynamically allocated memory +# stream/stream.c(525) : allocated -> leak : hostnamedup end scope : Memory leaked +74169ED2AA3FB0795C28912A9E687D77 # Not an issue. # Even if the data type for sr->id is defined as EVP_STREAM_PEER_ID, @@ -3407,20 +3334,6 @@ B6EA5D109BFEAA89BA2B58FCEAF41E47 # libevp-agent/main_loop.c(105) : <- getenv(return) 2292946D6DF27B0D6C5BFEDE04EBB3DA -# False positive. -# According to the documentation for NNG_OPT_TCP_BOUND_PORT, on -# nng_tcp_options(5): -# -# While the value is of type `int`, it will be a legal TCP port number, that -# is a value between 1 and 65535, inclusive. -# -# Therefore, there is no risk when assigning it into an unsigned short. -# [1F8D42C32A560CD0B51D7CFB4F3D55A3 : high : Type Mismatch : Signed to Unsigned : structural ] -# stream/nng.c(168) -# FieldAccess: p.port [stream/nng.c(168)] -# VariableAccess: port [stream/nng.c(168)] -1F8D42C32A560CD0B51D7CFB4F3D55A3 - # False positive # Fortify fails to see the ownership for `req` is # transferred in the call to EVP_impl_blobOperation and blob is diff --git a/tools/fortify/filter-sdk.txt b/tools/fortify/filter-sdk.txt index 02b1d260..6ee618bc 100644 --- a/tools/fortify/filter-sdk.txt +++ b/tools/fortify/filter-sdk.txt @@ -113,21 +113,6 @@ F86380716072F498F0206FB2ADD37348 # libevp-agent/stream/stream.c(543) : allocated -> leak : namedup end scope : Memory leaked E5BAF7C295BEB651FD2DBB5177CAC5CF -# False positive. Similar to E5BAF7C295BEB651FD2DBB5177CAC5CF. -# [A7652CC7EE4E2C7FADB3C4DA860B7064 : high : Memory Leak : controlflow ] -# -# libevp-app-sdk/sdk.c(1025) : Branch not taken: (params != NULL) -# libevp-app-sdk/sdk.c(1033) : Branch not taken: (connection != NULL) -# libevp-app-sdk/sdk.c(1039) : start -> allocated : connectiondup = strdup(...) -# libevp-app-sdk/sdk.c(1039) : allocated -> allocated : connectiondup refers to dynamically allocated memory -# libevp-app-sdk/sdk.c(1040) : Branch not taken: (connectiondup != NULL) -# libevp-app-sdk/sdk.c(1047) : allocated -> allocated : connectiondup refers to dynamically allocated memory -# libevp-app-sdk/sdk.c(1055) : Branch not taken: (ret == 0) -# libevp-app-sdk/sdk.c(1058) : allocated -> allocated : connectiondup no longer refers to dynamically allocated memory -# libevp-app-sdk/sdk.c(1058) : allocated -> allocated : .connection no longer refers to dynamically allocated memory -# libevp-app-sdk/sdk.c(1058) : allocated -> leak : end scope : Memory leaked -A7652CC7EE4E2C7FADB3C4DA860B7064 - # False positive. Similar to E5BAF7C295BEB651FD2DBB5177CAC5CF. # [EC095B6EAD3150351E9E6E34CE065126 : high : Memory Leak : controlflow ] # @@ -139,37 +124,20 @@ A7652CC7EE4E2C7FADB3C4DA860B7064 # libevp-agent/stream/stream.c(361) : allocated -> leak : event end scope : Memory leaked EC095B6EAD3150351E9E6E34CE065126 -# False positive. Similar to E5BAF7C295BEB651FD2DBB5177CAC5CF. -# [26FAD77FB5A912E51915B0447E01950B : high : Memory Leak : controlflow ] -# -# libevp-agent/stream/stream.c(476) : Branch not taken: (namedup != NULL) -# libevp-agent/stream/stream.c(486) : Branch taken: (src->type == 1) -# libevp-agent/stream/stream.c(486) : goto -# libevp-agent/stream/stream.c(490) : start -> allocated : connectiondup = strdup(...) -# libevp-agent/stream/stream.c(490) : allocated -> allocated : connectiondup refers to dynamically allocated memory -# libevp-agent/stream/stream.c(491) : Branch not taken: (connectiondup != NULL) -# libevp-agent/stream/stream.c(498) : allocated -> allocated : connectiondup refers to dynamically allocated memory -# libevp-agent/stream/stream.c(503) : allocated -> allocated : connectiondup no longer refers to dynamically allocated memory -# libevp-agent/stream/stream.c(538) : Branch not taken: (ret == 0) -# libevp-agent/stream/stream.c(543) : allocated -> allocated : connectiondup no longer refers to dynamically allocated memory -# libevp-agent/stream/stream.c(543) : allocated -> leak : connectiondup end scope : Memory leaked -26FAD77FB5A912E51915B0447E01950B - -#[021918F34229D07C933ED83A05B8936F : high : Memory Leak : controlflow ] -# -# evpmodulesdk/sdk.c(94) : Branch taken: (req != NULL) -# evpmodulesdk/sdk.c(96) : Branch taken: (req->resp != NULL) -# evpmodulesdk/sdk.c(100) : Branch taken: (h != NULL) -# evpmodulesdk/sdk.c(104) : Branch not taken: (ret == 0) -# evpmodulesdk/sdk.c(116) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) -# evpmodulesdk/sdk.c(123) : Branch not taken: (event_type != 3) -# evpmodulesdk/sdk.c(133) : Branch taken: (event_type == 1) -# evpmodulesdk/sdk.c(133) : goto -# evpmodulesdk/sdk.c(136) : start -> allocated : config = xmalloc(...) -# evpmodulesdk/sdk.c(136) : allocated -> allocated : config refers to dynamically allocated memory -# evpmodulesdk/sdk.c(147) : Branch not taken: (*h->events.tqh_last == NULL) -# evpmodulesdk/sdk.c(150) : allocated -> allocated : config no longer refers to dynamically allocated memory -# evpmodulesdk/sdk.c(150) : allocated -> leak : config end scope : Memory leaked +# [6BECED8E31EAFCD29B5E7BC15AAF1FDD : high : Memory Leak : controlflow ] +# +# libevp-app-sdk/sdk.c(104) : Branch taken: (req != NULL) +# libevp-app-sdk/sdk.c(106) : Branch taken: (req->resp != NULL) +# libevp-app-sdk/sdk.c(110) : Branch taken: (h != NULL) +# libevp-app-sdk/sdk.c(114) : Branch not taken: (ret == 0) +# libevp-app-sdk/sdk.c(126) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) +# libevp-app-sdk/sdk.c(133) : Branch not taken: (event_type != 3) +# libevp-app-sdk/sdk.c(143) : Branch taken: (event_type == 1) +# libevp-app-sdk/sdk.c(143) : goto +# libevp-app-sdk/sdk.c(146) : start -> allocated : config = xmalloc(...) +# libevp-app-sdk/sdk.c(146) : allocated -> allocated : config refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(160) : allocated -> allocated : config no longer refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(160) : allocated -> leak : config end scope : Memory leaked # # False positive: Fortify does not follow properly our code, when we use queues. # In get_event_done, we receive a Response in FlatBuffers format. @@ -186,158 +154,152 @@ EC095B6EAD3150351E9E6E34CE065126 # TAILQ_INSERT_TAIL(&h->events, &config->event, q); # It is the first element of the struct, so at the end is the same address. # -62BD6CC9A3041FA5D5C28253E85A2E8A - -# [665DA3BD2C75A9C1BE4FB49B452B9910 : high : Memory Leak : controlflow ] -# -# evpmodulesdk/sdk.c(94) : Branch taken: (req != NULL) -# evpmodulesdk/sdk.c(96) : Branch taken: (req->resp != NULL) -# evpmodulesdk/sdk.c(100) : Branch taken: (h != NULL) -# evpmodulesdk/sdk.c(104) : Branch not taken: (ret == 0) -# evpmodulesdk/sdk.c(116) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) -# evpmodulesdk/sdk.c(123) : Branch not taken: (event_type != 3) -# evpmodulesdk/sdk.c(151) : Branch taken: (event_type == 2) -# evpmodulesdk/sdk.c(151) : goto -# evpmodulesdk/sdk.c(154) : start -> allocated : state = xmalloc(...) -# evpmodulesdk/sdk.c(154) : allocated -> allocated : state refers to dynamically allocated memory -# evpmodulesdk/sdk.c(163) : Branch not taken: (*h->events.tqh_last == NULL) -# evpmodulesdk/sdk.c(166) : allocated -> allocated : state no longer refers to dynamically allocated memory -# evpmodulesdk/sdk.c(166) : allocated -> leak : state end scope : Memory leaked -# -# Same justification than in: 62BD6CC9A3041FA5D5C28253E85A2E8A -665DA3BD2C75A9C1BE4FB49B452B9910 - -# [B6AEA6E3137DDE6B46E8F66139B21D05 : high : Memory Leak : controlflow ] -# -# libevp-app-sdk/sdk.c(109) : Branch taken: (req != NULL) -# libevp-app-sdk/sdk.c(111) : Branch taken: (req->resp != NULL) -# libevp-app-sdk/sdk.c(115) : Branch taken: (h != NULL) -# libevp-app-sdk/sdk.c(119) : Branch not taken: (ret == 0) -# libevp-app-sdk/sdk.c(131) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) -# libevp-app-sdk/sdk.c(138) : Branch not taken: (event_type != 3) -# libevp-app-sdk/sdk.c(182) : Branch taken: (event_type == 4) -# libevp-app-sdk/sdk.c(182) : goto -# libevp-app-sdk/sdk.c(185) : start -> allocated : blob = xmalloc(...) -# libevp-app-sdk/sdk.c(185) : allocated -> allocated : blob refers to dynamically allocated memory -# libevp-app-sdk/sdk.c(197) : goto -# libevp-app-sdk/sdk.c(265) : allocated -> allocated : blob no longer refers to dynamically allocated memory -# libevp-app-sdk/sdk.c(265) : allocated -> leak : blob end scope : Memory leaked -# -# Same justification than in: 62BD6CC9A3041FA5D5C28253E85A2E8A -B6AEA6E3137DDE6B46E8F66139B21D05 - -# [3C7581FDD281BA4B93BF86B6A0673FCE : high : Memory Leak : controlflow ] -# -# evpmodulesdk/sdk.c(94) : Branch taken: (req != NULL) -# evpmodulesdk/sdk.c(96) : Branch taken: (req->resp != NULL) -# evpmodulesdk/sdk.c(100) : Branch taken: (h != NULL) -# evpmodulesdk/sdk.c(104) : Branch not taken: (ret == 0) -# evpmodulesdk/sdk.c(116) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) -# evpmodulesdk/sdk.c(123) : Branch not taken: (event_type != 3) -# evpmodulesdk/sdk.c(251) : Branch taken: (event_type == 7) -# evpmodulesdk/sdk.c(251) : goto -# evpmodulesdk/sdk.c(255) : start -> allocated : t = xmalloc(...) -# evpmodulesdk/sdk.c(255) : allocated -> allocated : t refers to dynamically allocated memory -# evpmodulesdk/sdk.c(264) : Branch not taken: (*h->events.tqh_last == NULL) -# evpmodulesdk/sdk.c(266) : allocated -> allocated : t no longer refers to dynamically allocated memory -# evpmodulesdk/sdk.c(266) : allocated -> leak : t end scope : Memory leaked -# -# Same justification than in: 62BD6CC9A3041FA5D5C28253E85A2E8A -3C7581FDD281BA4B93BF86B6A0673FCE - -# [65AD68D88420428179DA394BC062053A : high : Memory Leak : controlflow ] -# -# evpmodulesdk/sdk.c(94) : Branch taken: (req != NULL) -# evpmodulesdk/sdk.c(96) : Branch taken: (req->resp != NULL) -# evpmodulesdk/sdk.c(100) : Branch taken: (h != NULL) -# evpmodulesdk/sdk.c(104) : Branch not taken: (ret == 0) -# evpmodulesdk/sdk.c(116) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) -# evpmodulesdk/sdk.c(123) : Branch not taken: (event_type != 3) -# evpmodulesdk/sdk.c(267) : Branch taken: (event_type == 6) -# evpmodulesdk/sdk.c(267) : goto -# evpmodulesdk/sdk.c(271) : start -> allocated : m = xmalloc(...) -# evpmodulesdk/sdk.c(271) : allocated -> allocated : m refers to dynamically allocated memory -# evpmodulesdk/sdk.c(282) : Branch not taken: (*h->events.tqh_last == NULL) -# evpmodulesdk/sdk.c(284) : allocated -> allocated : m no longer refers to dynamically allocated memory -# evpmodulesdk/sdk.c(284) : allocated -> leak : m end scope : Memory leaked -# -# Same justification than in: 62BD6CC9A3041FA5D5C28253E85A2E8A -65AD68D88420428179DA394BC062053A - -# [223D718847FF6F14A459589470D14108 : high : Memory Leak : controlflow ] -# -# evpmodulesdk/sdk.c(94) : Branch taken: (req != NULL) -# evpmodulesdk/sdk.c(96) : Branch taken: (req->resp != NULL) -# evpmodulesdk/sdk.c(100) : Branch taken: (h != NULL) -# evpmodulesdk/sdk.c(104) : Branch not taken: (ret == 0) -# evpmodulesdk/sdk.c(116) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) -# evpmodulesdk/sdk.c(123) : Branch not taken: (event_type != 3) -# evpmodulesdk/sdk.c(285) : Branch taken: (event_type == 5) -# evpmodulesdk/sdk.c(285) : goto -# evpmodulesdk/sdk.c(289) : start -> allocated : m = xmalloc(...) -# evpmodulesdk/sdk.c(289) : allocated -> allocated : m refers to dynamically allocated memory -# evpmodulesdk/sdk.c(298) : Branch not taken: (*h->events.tqh_last == NULL) -# evpmodulesdk/sdk.c(300) : allocated -> allocated : m no longer refers to dynamically allocated memory -# evpmodulesdk/sdk.c(300) : allocated -> leak : m end scope : Memory leaked -# -# Same justification than in: 62BD6CC9A3041FA5D5C28253E85A2E8A -223D718847FF6F14A459589470D14108 - -# [7EE760949B13347BC41DB50D41BFE153 : high : Memory Leak : controlflow ] -# -# evpmodulesdk/sdk.c(94) : Branch taken: (req != NULL) -# evpmodulesdk/sdk.c(96) : Branch taken: (req->resp != NULL) -# evpmodulesdk/sdk.c(100) : Branch taken: (h != NULL) -# evpmodulesdk/sdk.c(104) : Branch not taken: (ret == 0) -# evpmodulesdk/sdk.c(116) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) -# evpmodulesdk/sdk.c(123) : Branch not taken: (event_type != 3) -# evpmodulesdk/sdk.c(301) : Branch taken: (event_type == 8) -# evpmodulesdk/sdk.c(301) : goto -# evpmodulesdk/sdk.c(304) : start -> allocated : r = xmalloc(...) -# evpmodulesdk/sdk.c(304) : allocated -> allocated : r refers to dynamically allocated memory -# evpmodulesdk/sdk.c(312) : Branch not taken: (*h->events.tqh_last == NULL) -# evpmodulesdk/sdk.c(314) : allocated -> allocated : r no longer refers to dynamically allocated memory -# evpmodulesdk/sdk.c(314) : allocated -> leak : r end scope : Memory leaked -# -# Same justification than in: 62BD6CC9A3041FA5D5C28253E85A2E8A -7EE760949B13347BC41DB50D41BFE153 - -# [1B5DC44A2958BF7578A974B7D1F9CBF8 : high : Memory Leak : controlflow ] -# -# evpmodulesdk/sdk.c(94) : Branch taken: (req != NULL) -# evpmodulesdk/sdk.c(96) : Branch taken: (req->resp != NULL) -# evpmodulesdk/sdk.c(100) : Branch taken: (h != NULL) -# evpmodulesdk/sdk.c(104) : Branch not taken: (ret == 0) -# evpmodulesdk/sdk.c(116) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) -# evpmodulesdk/sdk.c(123) : Branch not taken: (event_type != 3) -# evpmodulesdk/sdk.c(315) : Branch taken: (event_type == 9) -# evpmodulesdk/sdk.c(315) : goto -# evpmodulesdk/sdk.c(319) : start -> allocated : r = xmalloc(...) -# evpmodulesdk/sdk.c(319) : allocated -> allocated : r refers to dynamically allocated memory -# evpmodulesdk/sdk.c(328) : Branch not taken: (*h->events.tqh_last == NULL) -# evpmodulesdk/sdk.c(330) : allocated -> allocated : r no longer refers to dynamically allocated memory -# evpmodulesdk/sdk.c(330) : allocated -> leak : r end scope : Memory leaked -# -# Same justification than in: 62BD6CC9A3041FA5D5C28253E85A2E8A -1B5DC44A2958BF7578A974B7D1F9CBF8 +6BECED8E31EAFCD29B5E7BC15AAF1FDD + +# [31573DA6474BF1CCBA709A528D24DBCC : high : Memory Leak : controlflow ] +# +# libevp-app-sdk/sdk.c(104) : Branch taken: (req != NULL) +# libevp-app-sdk/sdk.c(106) : Branch taken: (req->resp != NULL) +# libevp-app-sdk/sdk.c(110) : Branch taken: (h != NULL) +# libevp-app-sdk/sdk.c(114) : Branch not taken: (ret == 0) +# libevp-app-sdk/sdk.c(126) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) +# libevp-app-sdk/sdk.c(133) : Branch not taken: (event_type != 3) +# libevp-app-sdk/sdk.c(161) : Branch taken: (event_type == 2) +# libevp-app-sdk/sdk.c(161) : goto +# libevp-app-sdk/sdk.c(164) : start -> allocated : state = xmalloc(...) +# libevp-app-sdk/sdk.c(164) : allocated -> allocated : state refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(176) : allocated -> allocated : state no longer refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(176) : allocated -> leak : state end scope : Memory leaked +# +# Same justification than in: 6BECED8E31EAFCD29B5E7BC15AAF1FDD +31573DA6474BF1CCBA709A528D24DBCC + +# [1CA522911595C8BABF32803DCDBE2A96 : high : Memory Leak : controlflow ] +# +# libevp-app-sdk/sdk.c(104) : Branch taken: (req != NULL) +# libevp-app-sdk/sdk.c(106) : Branch taken: (req->resp != NULL) +# libevp-app-sdk/sdk.c(110) : Branch taken: (h != NULL) +# libevp-app-sdk/sdk.c(114) : Branch not taken: (ret == 0) +# libevp-app-sdk/sdk.c(126) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) +# libevp-app-sdk/sdk.c(133) : Branch not taken: (event_type != 3) +# libevp-app-sdk/sdk.c(177) : Branch taken: (event_type == 4) +# libevp-app-sdk/sdk.c(177) : goto +# libevp-app-sdk/sdk.c(180) : start -> allocated : blob = xmalloc(...) +# libevp-app-sdk/sdk.c(180) : allocated -> allocated : blob refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(192) : goto +# libevp-app-sdk/sdk.c(260) : allocated -> allocated : blob no longer refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(260) : allocated -> leak : blob end scope : Memory leaked +# +# Same justification than in: 6BECED8E31EAFCD29B5E7BC15AAF1FDD +1CA522911595C8BABF32803DCDBE2A96 + +# [FE42DC481FA854957010E17498F565ED : high : Memory Leak : controlflow ] +# +# libevp-app-sdk/sdk.c(104) : Branch taken: (req != NULL) +# libevp-app-sdk/sdk.c(106) : Branch taken: (req->resp != NULL) +# libevp-app-sdk/sdk.c(110) : Branch taken: (h != NULL) +# libevp-app-sdk/sdk.c(114) : Branch not taken: (ret == 0) +# libevp-app-sdk/sdk.c(126) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) +# libevp-app-sdk/sdk.c(133) : Branch not taken: (event_type != 3) +# libevp-app-sdk/sdk.c(261) : Branch taken: (event_type == 7) +# libevp-app-sdk/sdk.c(261) : goto +# libevp-app-sdk/sdk.c(265) : start -> allocated : t = xmalloc(...) +# libevp-app-sdk/sdk.c(265) : allocated -> allocated : t refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(276) : allocated -> allocated : t no longer refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(276) : allocated -> leak : t end scope : Memory leaked +# +# Same justification than in: 6BECED8E31EAFCD29B5E7BC15AAF1FDD +FE42DC481FA854957010E17498F565ED + +# [46E0976A4B4294C72B70D1F52BC94A1A : high : Memory Leak : controlflow ] +# +# libevp-app-sdk/sdk.c(104) : Branch taken: (req != NULL) +# libevp-app-sdk/sdk.c(106) : Branch taken: (req->resp != NULL) +# libevp-app-sdk/sdk.c(110) : Branch taken: (h != NULL) +# libevp-app-sdk/sdk.c(114) : Branch not taken: (ret == 0) +# libevp-app-sdk/sdk.c(126) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) +# libevp-app-sdk/sdk.c(133) : Branch not taken: (event_type != 3) +# libevp-app-sdk/sdk.c(277) : Branch taken: (event_type == 6) +# libevp-app-sdk/sdk.c(277) : goto +# libevp-app-sdk/sdk.c(281) : start -> allocated : m = xmalloc(...) +# libevp-app-sdk/sdk.c(281) : allocated -> allocated : m refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(294) : allocated -> allocated : m no longer refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(294) : allocated -> leak : m end scope : Memory leaked +# +# Same justification than in: 6BECED8E31EAFCD29B5E7BC15AAF1FDD +46E0976A4B4294C72B70D1F52BC94A1A + +# [1D8790E2DFD741E844E1E1CD77D99B85 : high : Memory Leak : controlflow ] +# +# libevp-app-sdk/sdk.c(104) : Branch taken: (req != NULL) +# libevp-app-sdk/sdk.c(106) : Branch taken: (req->resp != NULL) +# libevp-app-sdk/sdk.c(110) : Branch taken: (h != NULL) +# libevp-app-sdk/sdk.c(114) : Branch not taken: (ret == 0) +# libevp-app-sdk/sdk.c(126) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) +# libevp-app-sdk/sdk.c(133) : Branch not taken: (event_type != 3) +# libevp-app-sdk/sdk.c(295) : Branch taken: (event_type == 5) +# libevp-app-sdk/sdk.c(295) : goto +# libevp-app-sdk/sdk.c(299) : start -> allocated : m = xmalloc(...) +# libevp-app-sdk/sdk.c(299) : allocated -> allocated : m refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(310) : allocated -> allocated : m no longer refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(310) : allocated -> leak : m end scope : Memory leaked +# +# Same justification than in: 6BECED8E31EAFCD29B5E7BC15AAF1FDD +1D8790E2DFD741E844E1E1CD77D99B85 + +# [6B80B9BB335AA182BA410E34B0044CBF : high : Memory Leak : controlflow ] +# +# libevp-app-sdk/sdk.c(104) : Branch taken: (req != NULL) +# libevp-app-sdk/sdk.c(106) : Branch taken: (req->resp != NULL) +# libevp-app-sdk/sdk.c(110) : Branch taken: (h != NULL) +# libevp-app-sdk/sdk.c(114) : Branch not taken: (ret == 0) +# libevp-app-sdk/sdk.c(126) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) +# libevp-app-sdk/sdk.c(133) : Branch not taken: (event_type != 3) +# libevp-app-sdk/sdk.c(311) : Branch taken: (event_type == 8) +# libevp-app-sdk/sdk.c(311) : goto +# libevp-app-sdk/sdk.c(314) : start -> allocated : r = xmalloc(...) +# libevp-app-sdk/sdk.c(314) : allocated -> allocated : r refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(324) : allocated -> allocated : r no longer refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(324) : allocated -> leak : r end scope : Memory leaked +# +# Same justification than in: 6BECED8E31EAFCD29B5E7BC15AAF1FDD +6B80B9BB335AA182BA410E34B0044CBF + +# [1C8B3D7F573A6BCF4E57146791121F5D : high : Memory Leak : controlflow ] +# +# libevp-app-sdk/sdk.c(104) : Branch taken: (req != NULL) +# libevp-app-sdk/sdk.c(106) : Branch taken: (req->resp != NULL) +# libevp-app-sdk/sdk.c(110) : Branch taken: (h != NULL) +# libevp-app-sdk/sdk.c(114) : Branch not taken: (ret == 0) +# libevp-app-sdk/sdk.c(126) : Branch taken: (EVP_SDK_Response_body_type(resp) == 1) +# libevp-app-sdk/sdk.c(133) : Branch not taken: (event_type != 3) +# libevp-app-sdk/sdk.c(325) : Branch taken: (event_type == 9) +# libevp-app-sdk/sdk.c(325) : goto +# libevp-app-sdk/sdk.c(329) : start -> allocated : r = xmalloc(...) +# libevp-app-sdk/sdk.c(329) : allocated -> allocated : r refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(340) : allocated -> allocated : r no longer refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(340) : allocated -> leak : r end scope : Memory leaked +# +# Same justification than in: 6BECED8E31EAFCD29B5E7BC15AAF1FDD +1C8B3D7F573A6BCF4E57146791121F5D # False positive. # Yet again, Fortify fails to see the struct Stream compound literal is # transferred to "s", which is then transferred to "stream", so no objects # are being leaked. -# [ED473AC9E862F8946CD298692F6C47B7 : high : Memory Leak : controlflow ] -# -# libevp-app-sdk/sdk.c(1068) : Branch not taken: (error == 0) -# libevp-app-sdk/sdk.c(1076) : Branch not taken: (resp != NULL) -# libevp-app-sdk/sdk.c(1083) : Branch not taken: (type == 3) -# libevp-app-sdk/sdk.c(1091) : Branch not taken: (body != NULL) -# libevp-app-sdk/sdk.c(1099) : Branch not taken: (ret == 0) -# libevp-app-sdk/sdk.c(1103) : start -> allocated : .name = strdup(...) -# libevp-app-sdk/sdk.c(1103) : allocated -> allocated : .name refers to dynamically allocated memory -# libevp-app-sdk/sdk.c(1112) : goto -# libevp-app-sdk/sdk.c(1138) : allocated -> allocated : .name no longer refers to dynamically allocated memory -# libevp-app-sdk/sdk.c(1138) : allocated -> leak : end scope : Memory leaked -ED473AC9E862F8946CD298692F6C47B7 +# [6D9CD92CF4AE13E28081815C47C5B94A : high : Memory Leak : controlflow ] +# +# libevp-app-sdk/sdk.c(1022) : Branch not taken: (error == 0) +# libevp-app-sdk/sdk.c(1030) : Branch not taken: (resp != NULL) +# libevp-app-sdk/sdk.c(1037) : Branch not taken: (type == 3) +# libevp-app-sdk/sdk.c(1045) : Branch not taken: (body != NULL) +# libevp-app-sdk/sdk.c(1053) : Branch not taken: (ret == 0) +# libevp-app-sdk/sdk.c(1057) : start -> allocated : .name = strdup(...) +# libevp-app-sdk/sdk.c(1057) : allocated -> allocated : .name refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(1066) : goto +# libevp-app-sdk/sdk.c(1091) : allocated -> allocated : .name no longer refers to dynamically allocated memory +# libevp-app-sdk/sdk.c(1091) : allocated -> leak : end scope : Memory leaked +6D9CD92CF4AE13E28081815C47C5B94A # False positive. # Fortify fails to see the ownership for event is transferred to the @@ -355,79 +317,6 @@ ED473AC9E862F8946CD298692F6C47B7 # libevp-agent/stream/stream.c(361) : allocated -> leak : end scope : Memory leaked FAB645EE0389BCEEDFF7466521CF7A24 -# False positive. -# Yet again, Fortify fails to see the ownership for nng is transferred to -# si->params if successful, or freed otherwise. -# [1A885094842BD658D060434C33161244 : high : Memory Leak : controlflow ] -# -# stream/nng.c(81) : start -> allocated : nng = malloc(...) -# stream/nng.c(81) : allocated -> allocated : nng refers to dynamically allocated memory -# stream/nng.c(83) : Branch not taken: (nng != NULL) -# stream/nng.c(102) : Branch taken: (cfg->protocol == 1) -# stream/nng.c(102) : goto -# stream/nng.c(104) : Branch taken: (error != 0) -# stream/nng.c(107) : allocated -> allocated : return -# stream/nng.c(107) : allocated -> allocated : nng no longer refers to dynamically allocated memory -# stream/nng.c(107) : allocated -> leak : nng end scope : Memory leaked -# -# stream/nng.c(81) : start -> allocated : nng = malloc(...) -# stream/nng.c(81) : allocated -> allocated : nng refers to dynamically allocated memory -# stream/nng.c(83) : Branch not taken: (nng != NULL) -# stream/nng.c(93) : Default case -# stream/nng.c(112) : Branch taken: (cfg->mode == 0) -# stream/nng.c(112) : goto -# stream/nng.c(115) : Branch taken: (error != 0) -# stream/nng.c(118) : allocated -> allocated : return -# stream/nng.c(118) : allocated -> allocated : nng no longer refers to dynamically allocated memory -# stream/nng.c(118) : allocated -> leak : nng end scope : Memory leaked -# -# stream/nng.c(81) : start -> allocated : nng = malloc(...) -# stream/nng.c(81) : allocated -> allocated : nng refers to dynamically allocated memory -# stream/nng.c(83) : Branch not taken: (nng != NULL) -# stream/nng.c(93) : Default case -# stream/nng.c(128) : Branch taken: (cfg->mode == 1) -# stream/nng.c(128) : goto -# stream/nng.c(131) : Branch taken: (error != 0) -# stream/nng.c(134) : allocated -> allocated : return -# stream/nng.c(134) : allocated -> allocated : nng no longer refers to dynamically allocated memory -# stream/nng.c(134) : allocated -> leak : nng end scope : Memory leaked -# -# stream/nng.c(81) : start -> allocated : nng = malloc(...) -# stream/nng.c(81) : allocated -> allocated : nng refers to dynamically allocated memory -# stream/nng.c(83) : Branch not taken: (nng != NULL) -# stream/nng.c(94) : Branch taken: (cfg->protocol == 0) -# stream/nng.c(94) : goto -# stream/nng.c(96) : Branch taken: (error != 0) -# stream/nng.c(99) : goto -# stream/nng.c(148) : Branch not taken: (ret == 0) -# stream/nng.c(154) : allocated -> allocated : nng no longer refers to dynamically allocated memory -# stream/nng.c(154) : allocated -> leak : nng end scope : Memory leaked -# -# stream/nng.c(81) : start -> allocated : nng = malloc(...) -# stream/nng.c(81) : allocated -> allocated : nng refers to dynamically allocated memory -# stream/nng.c(83) : Branch not taken: (nng != NULL) -# stream/nng.c(93) : Default case -# stream/nng.c(112) : Branch taken: (cfg->mode == 0) -# stream/nng.c(112) : goto -# stream/nng.c(115) : Branch not taken: (error == 0) -# stream/nng.c(122) : Branch taken: (error != 0) -# stream/nng.c(125) : allocated -> allocated : return -# stream/nng.c(125) : allocated -> allocated : nng no longer refers to dynamically allocated memory -# stream/nng.c(125) : allocated -> leak : nng end scope : Memory leaked -# -# stream/nng.c(81) : start -> allocated : nng = malloc(...) -# stream/nng.c(81) : allocated -> allocated : nng refers to dynamically allocated memory -# stream/nng.c(83) : Branch not taken: (nng != NULL) -# stream/nng.c(93) : Default case -# stream/nng.c(128) : Branch taken: (cfg->mode == 1) -# stream/nng.c(128) : goto -# stream/nng.c(131) : Branch not taken: (error == 0) -# stream/nng.c(138) : Branch taken: (error != 0) -# stream/nng.c(141) : allocated -> allocated : return -# stream/nng.c(141) : allocated -> allocated : nng no longer refers to dynamically allocated memory -# stream/nng.c(141) : allocated -> leak : nng end scope : Memory leaked -1A885094842BD658D060434C33161244 - # False positive. # Yet again, Fortify fails to see the ownership for si is transferred on the # call to stream_insert when successful, or freed otherwise. @@ -507,20 +396,20 @@ BA0F36F9B53D08073B3E0230D7DE21EB # False positive. # Yet again, Fortify fails to see the ownership for hostnamedup is transferred # to params.posix when the function is succesful. -# [E420D9DB4AAAEC85F8B479ADC95EDBF9 : high : Memory Leak : controlflow ] -# -# libevp-agent/stream/stream.c(476) : Branch not taken: (namedup != NULL) -# libevp-agent/stream/stream.c(505) : Branch taken: (src->type == 2) -# libevp-agent/stream/stream.c(505) : goto -# libevp-agent/stream/stream.c(509) : start -> allocated : hostnamedup = strdup(...) -# libevp-agent/stream/stream.c(509) : allocated -> allocated : hostnamedup refers to dynamically allocated memory -# libevp-agent/stream/stream.c(510) : Branch not taken: (hostnamedup != NULL) -# libevp-agent/stream/stream.c(519) : allocated -> allocated : hostnamedup refers to dynamically allocated memory -# libevp-agent/stream/stream.c(523) : allocated -> allocated : hostnamedup no longer refers to dynamically allocated memory -# libevp-agent/stream/stream.c(538) : Branch not taken: (ret == 0) -# libevp-agent/stream/stream.c(543) : allocated -> allocated : hostnamedup no longer refers to dynamically allocated memory -# libevp-agent/stream/stream.c(543) : allocated -> leak : hostnamedup end scope : Memory leaked -E420D9DB4AAAEC85F8B479ADC95EDBF9 +# [74169ED2AA3FB0795C28912A9E687D77 : high : Memory Leak : controlflow ] +# +# libevp-agent/stream/stream.c(477) : Branch not taken: (namedup != NULL) +# libevp-agent/stream/stream.c(487) : Branch taken: (src->type == 1) +# libevp-agent/stream/stream.c(487) : goto +# libevp-agent/stream/stream.c(491) : start -> allocated : hostnamedup = strdup(...) +# libevp-agent/stream/stream.c(491) : allocated -> allocated : hostnamedup refers to dynamically allocated memory +# libevp-agent/stream/stream.c(492) : Branch not taken: (hostnamedup != NULL) +# libevp-agent/stream/stream.c(501) : allocated -> allocated : hostnamedup refers to dynamically allocated memory +# libevp-agent/stream/stream.c(505) : allocated -> allocated : hostnamedup no longer refers to dynamically allocated memory +# libevp-agent/stream/stream.c(520) : Branch not taken: (ret == 0) +# libevp-agent/stream/stream.c(525) : allocated -> allocated : hostnamedup no longer refers to dynamically allocated memory +# libevp-agent/stream/stream.c(525) : allocated -> leak : hostnamedup end scope : Memory leaked +74169ED2AA3FB0795C28912A9E687D77 # Not an issue. # Even if the data type for sr->id is defined as EVP_STREAM_PEER_ID, @@ -612,17 +501,3 @@ AB82561AD6FCF66BC65E7AFFCCBCC835 # notification.c(86) : allocated -> allocated : .event no longer refers to dynamically allocated memory # notification.c(86) : allocated -> leak : end scope : Memory leaked 94637FA846AF053377DDFE701AE8B068 - -# False positive. -# According to the documentation for NNG_OPT_TCP_BOUND_PORT, on -# nng_tcp_options(5): -# -# While the value is of type `int`, it will be a legal TCP port number, that -# is a value between 1 and 65535, inclusive. -# -# Therefore, there is no risk when assigning it into an unsigned short. -# [1F8D42C32A560CD0B51D7CFB4F3D55A3 : high : Type Mismatch : Signed to Unsigned : structural ] -# stream/nng.c(168) -# FieldAccess: p.port [stream/nng.c(168)] -# VariableAccess: port [stream/nng.c(168)] -1F8D42C32A560CD0B51D7CFB4F3D55A3 diff --git a/tools/fortify/rules.xml b/tools/fortify/rules.xml index fd7e9b3b..5fabe3bc 100644 --- a/tools/fortify/rules.xml +++ b/tools/fortify/rules.xml @@ -9,12 +9,12 @@ SPDX-License-Identifier: Apache-2.0 94923a24-0582-11ec-b8c0-573a9c68bf17 0000.0.0.0000 cpp diff --git a/version.mk b/version.mk index c96c3864..7942426b 100644 --- a/version.mk +++ b/version.mk @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -VERSION = 1.42.0 +VERSION = 1.43.0 COMMIT_HASH = $(shell git describe --always --abbrev=0 --dirty --match "NOT A TAG") define VERSION_BODY