├── .clusterfuzzlite ├── Dockerfile ├── README.md ├── build.sh ├── project.yaml └── validate_fuzzer.c ├── .github ├── .cSpellWords.txt ├── CODEOWNERS ├── CONTRIBUTING.md ├── memory_statistics_config.json ├── pull_request_template.md └── workflows │ ├── cflite_pr.yml │ ├── ci.yml │ ├── doxygen.yml │ └── release.yml ├── .gitignore ├── .gitmodules ├── .lgtm.yml ├── CHANGELOG.md ├── LICENSE ├── MISRA.md ├── README.md ├── SECURITY.md ├── cspell.config.yaml ├── docs └── doxygen │ ├── config.doxyfile │ ├── include │ └── size_table.md │ ├── layout.xml │ ├── pages.dox │ └── style.css ├── jsonFilePaths.cmake ├── loop_invariants.patch ├── manifest.yml ├── source ├── core_json.c └── include │ ├── core_json.h │ ├── stdbool.readme │ └── stdint.readme ├── test ├── CMakeLists.txt ├── cbmc │ ├── .gitignore │ ├── include │ │ ├── README.md │ │ ├── core_json_annex.h │ │ └── core_json_contracts.h │ ├── proofs │ │ ├── JSON_Iterate │ │ │ ├── JSON_Iterate_harness.c │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ └── cbmc-viewer.json │ │ ├── JSON_SearchConst │ │ │ ├── JSON_SearchConst_harness.c │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ └── cbmc-viewer.json │ │ ├── JSON_Validate │ │ │ ├── JSON_Validate_harness.c │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ └── cbmc-viewer.json │ │ ├── Makefile │ │ ├── Makefile-json.common │ │ ├── Makefile-project-defines │ │ ├── Makefile-project-targets │ │ ├── Makefile-project-testing │ │ ├── Makefile-template-defines │ │ ├── Makefile.common │ │ ├── README.md │ │ ├── arraySearch │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── arraySearch_harness.c │ │ │ ├── cbmc-proof.txt │ │ │ └── cbmc-viewer.json │ │ ├── lib │ │ │ ├── __init__.py │ │ │ ├── print_tool_versions.py │ │ │ └── summarize.py │ │ ├── multiSearch │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ ├── cbmc-viewer.json │ │ │ └── multiSearch_harness.c │ │ ├── objectSearch │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ ├── cbmc-viewer.json │ │ │ └── objectSearch_harness.c │ │ ├── run-cbmc-proofs.py │ │ ├── skipAnyScalar │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ ├── cbmc-viewer.json │ │ │ └── skipAnyScalar_harness.c │ │ ├── skipCollection │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ ├── cbmc-viewer.json │ │ │ └── skipCollection_harness.c │ │ ├── skipDigits │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ ├── cbmc-viewer.json │ │ │ └── skipDigits_harness.c │ │ ├── skipEscape │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ ├── cbmc-viewer.json │ │ │ └── skipEscape_harness.c │ │ ├── skipObjectScalars │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ ├── cbmc-viewer.json │ │ │ └── skipObjectScalars_harness.c │ │ ├── skipScalars │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ ├── cbmc-viewer.json │ │ │ └── skipScalars_harness.c │ │ ├── skipSpace │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ ├── cbmc-viewer.json │ │ │ └── skipSpace_harness.c │ │ ├── skipString │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ ├── cbmc-viewer.json │ │ │ └── skipString_harness.c │ │ └── skipUTF8 │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── cbmc-proof.txt │ │ │ ├── cbmc-viewer.json │ │ │ └── skipUTF8_harness.c │ └── sources │ │ ├── README.md │ │ └── core_json_contracts.c └── unit-test │ ├── CMakeLists.txt │ ├── catch_assert.h │ ├── core_json_utest.c │ └── unity_build.cmake └── tools ├── coverity ├── README.md └── misra.config └── unity ├── coverage.cmake ├── create_test.cmake └── project.yml /.clusterfuzzlite/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcr.io/oss-fuzz-base/base-builder 2 | RUN apt-get update && apt-get install -y make autoconf automake libtool 3 | 4 | COPY . $SRC/corejson 5 | COPY .clusterfuzzlite/build.sh $SRC/build.sh 6 | WORKDIR $SRC/corejson 7 | -------------------------------------------------------------------------------- /.clusterfuzzlite/README.md: -------------------------------------------------------------------------------- 1 | # ClusterFuzzLite set up 2 | 3 | This folder contains a fuzzing set for [ClusterFuzzLite](https://google.github.io/clusterfuzzlite). 4 | 5 | 6 | ## Running the fuzzer locally 7 | 8 | To reproduce the fuzzing by way of [OSS-Fuzz](https://github.com/google/oss-fuzz) (which ClusterFuzzLite will be using): 9 | 10 | ```sh 11 | git clone https://github.com/google/oss-fuzz 12 | 13 | # Notice the destination folder shuold be in lower case. 14 | git clone https://github.com/FreeRTOS/coreJSON corejson 15 | cd corejson 16 | 17 | # Build the fuzzers in .clusterfuzzlite 18 | python3 ../oss-fuzz/infra/helper.py build_fuzzers --external $PWD 19 | 20 | # Run the fuzzer for 180 seconds 21 | python3 ../oss-fuzz/infra/helper.py run_fuzzer --external $PWD validate_fuzzer -- -max_total_time=180 22 | ``` 23 | -------------------------------------------------------------------------------- /.clusterfuzzlite/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | # Copy the fuzzer executable to $OUT/ 4 | $CC $CFLAGS $LIB_FUZZING_ENGINE \ 5 | $SRC/corejson/.clusterfuzzlite/validate_fuzzer.c \ 6 | $SRC/corejson/source/core_json.c \ 7 | -I$SRC/corejson/source/include \ 8 | -o $OUT/validate_fuzzer 9 | -------------------------------------------------------------------------------- /.clusterfuzzlite/project.yaml: -------------------------------------------------------------------------------- 1 | language: c 2 | -------------------------------------------------------------------------------- /.clusterfuzzlite/validate_fuzzer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 5 | JSON_Validate((char *)data, size); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /.github/.cSpellWords.txt: -------------------------------------------------------------------------------- 1 | cbmc 2 | CBMC 3 | cbor 4 | CBOR 5 | cmock 6 | Cmock 7 | CMock 8 | CMOCK 9 | coremqtt 10 | coverity 11 | Coverity 12 | CSDK 13 | ctest 14 | DCMOCK 15 | decihours 16 | Decihours 17 | DECIHOURS 18 | dfcc 19 | DNDEBUG 20 | DUNITY 21 | EFFF 22 | getpacketid 23 | isystem 24 | lcov 25 | misra 26 | Misra 27 | MISRA 28 | MQTT 29 | mypy 30 | nondet 31 | Nondet 32 | NONDET 33 | pylint 34 | pytest 35 | pyyaml 36 | searcht 37 | sinclude 38 | strn 39 | UNACKED 40 | unpadded 41 | Unpadded 42 | UNPADDED 43 | UNSUB 44 | UNSUBACK 45 | unsubscriptions 46 | utest 47 | vect 48 | Vect 49 | VECT 50 | Wunused 51 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Each line is a file pattern followed by one or more owners. 2 | 3 | # These owners will be the default owners for everything in 4 | # the repo. Unless a later match takes precedence, 5 | # @global-owner1 and @global-owner2 will be requested for 6 | # review when someone opens a pull request. 7 | * @FreeRTOS/pr-bar-raiser 8 | 9 | # Order is important; the last matching pattern takes the most 10 | # precedence. When someone opens a pull request that only 11 | # modifies c files, only @FreeRTOS/pr-bar-raiser and not the 12 | # global owner(s) will be requested for a review. 13 | # *.c FreeRTOS/pr-bar-raiser 14 | 15 | # You can also use email addresses if you prefer. They'll be 16 | # used to look up users just like we do for commit author 17 | # emails. 18 | # *.go docs@example.com 19 | 20 | # In this example, @doctocat owns any files in the build/logs 21 | # directory at the root of the repository and any of its 22 | # subdirectories. 23 | # /build/logs/ @doctocat 24 | 25 | # The `docs/*` pattern will match files like 26 | # `docs/getting-started.md` but not further nested files like 27 | # `docs/build-app/troubleshooting.md`. 28 | # docs/* docs@example.com 29 | 30 | # In this example, @octocat owns any file in an apps directory 31 | # anywhere in your repository. 32 | # apps/ @octocat 33 | 34 | # In this example, @doctocat owns any file in the `/docs` 35 | # directory in the root of your repository and any of its 36 | # subdirectories. 37 | # /docs/ @doctocat 38 | 39 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/FreeRTOS/coreJSON/issues), or [recently closed](https://github.com/FreeRTOS/coreJSON/issues?q=is%3Aissue+is%3Aclosed), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 1. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 1. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 1. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 1. Ensure that your contributions conform to the [style guide](https://docs.aws.amazon.com/embedded-csdk/202011.00/lib-ref/docs/doxygen/output/html/guide_developer_styleguide.html). 35 | 1. Format your code with uncrustify, using the config available in [FreeRTOS/CI-CD-Github-Actions](https://github.com/FreeRTOS/CI-CD-Github-Actions/blob/main/formatting/uncrustify.cfg). 36 | 1. Ensure local tests pass. 37 | 1. Commit to your fork using clear commit messages. 38 | 1. Send us a pull request, answering any default questions in the pull request interface. 39 | 1. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 40 | 41 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 42 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 43 | 44 | 45 | ## Finding contributions to work on 46 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/FreeRTOS/coreJSON/labels?q=help+wanted) issues is a great place to start. 47 | 48 | 49 | ## Code of Conduct 50 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 51 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 52 | opensource-codeofconduct@amazon.com with any additional questions or comments. 53 | 54 | 55 | ## Security issue notifications 56 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 57 | 58 | 59 | ## Licensing 60 | 61 | See the [LICENSE](../LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 62 | 63 | We may ask you to sign a [Contributor License Agreement (CLA)](https://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 64 | -------------------------------------------------------------------------------- /.github/memory_statistics_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib_name" : "coreJSON", 3 | "src": [ 4 | "source/core_json.c" 5 | ], 6 | "include": [ 7 | "source/include" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Description 4 | ----------- 5 | 6 | 7 | Test Steps 8 | ----------- 9 | 10 | 11 | Checklist: 12 | ---------- 13 | 14 | 15 | - [ ] I have tested my changes. No regression in existing tests. 16 | - [ ] I have modified and/or added unit-tests to cover the code changes in this Pull Request. 17 | 18 | Related Issue 19 | ----------- 20 | 21 | By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. 22 | -------------------------------------------------------------------------------- /.github/workflows/cflite_pr.yml: -------------------------------------------------------------------------------- 1 | name: ClusterFuzzLite PR fuzzing 2 | on: 3 | workflow_dispatch: 4 | pull_request: 5 | branches: [ main ] 6 | permissions: read-all 7 | jobs: 8 | PR: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | sanitizer: [address] 14 | steps: 15 | - name: Build Fuzzers (${{ matrix.sanitizer }}) 16 | id: build 17 | uses: google/clusterfuzzlite/actions/build_fuzzers@v1 18 | with: 19 | sanitizer: ${{ matrix.sanitizer }} 20 | language: c 21 | bad-build-check: false 22 | - name: Run Fuzzers (${{ matrix.sanitizer }}) 23 | id: run 24 | uses: google/clusterfuzzlite/actions/run_fuzzers@v1 25 | with: 26 | github-token: ${{ secrets.GITHUB_TOKEN }} 27 | fuzz-seconds: 180 28 | mode: 'code-change' 29 | report-unreproducible-crashes: false 30 | sanitizer: ${{ matrix.sanitizer }} 31 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI Checks 2 | on: 3 | push: 4 | branches: ["**"] 5 | pull_request: 6 | branches: [main] 7 | workflow_dispatch: 8 | jobs: 9 | unittest: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Clone This Repo 13 | uses: actions/checkout@v3 14 | - name: Build 15 | run: | 16 | sudo apt-get install -y lcov sed 17 | cmake -S test -B build/ \ 18 | -G "Unix Makefiles" \ 19 | -DCMAKE_BUILD_TYPE=Debug \ 20 | -DBUILD_CLONE_SUBMODULES=ON \ 21 | -DCMAKE_C_FLAGS='--coverage -Wall -Wextra -Werror' 22 | make -C build/ all 23 | - name: Test 24 | run: | 25 | cd build/ 26 | ctest -E system --output-on-failure 27 | cd .. 28 | - name: Run Coverage 29 | run: | 30 | make -C build/ coverage 31 | declare -a EXCLUDE=("\*test\*" "\*CMakeCCompilerId\*" "\*mocks\*" "\*source\*") 32 | echo ${EXCLUDE[@]} | xargs lcov --rc lcov_branch_coverage=1 -r build/coverage.info -o build/coverage.info 33 | lcov --rc lcov_branch_coverage=1 --list build/coverage.info 34 | - name: Check Coverage 35 | uses: FreeRTOS/CI-CD-Github-Actions/coverage-cop@main 36 | with: 37 | coverage-file: ./build/coverage.info 38 | 39 | complexity: 40 | runs-on: ubuntu-latest 41 | steps: 42 | - uses: actions/checkout@v3 43 | - name: Check complexity 44 | uses: FreeRTOS/CI-CD-Github-Actions/complexity@main 45 | with: 46 | path: ./ 47 | horrid_threshold: 12 48 | 49 | doxygen: 50 | runs-on: ubuntu-latest 51 | steps: 52 | - uses: actions/checkout@v3 53 | - name: Run doxygen build 54 | uses: FreeRTOS/CI-CD-Github-Actions/doxygen@main 55 | with: 56 | path: ./ 57 | 58 | spell-check: 59 | runs-on: ubuntu-latest 60 | steps: 61 | - name: Clone This Repo 62 | uses: actions/checkout@v3 63 | - name: Run spellings check 64 | uses: FreeRTOS/CI-CD-Github-Actions/spellings@main 65 | with: 66 | path: ./ 67 | 68 | formatting: 69 | runs-on: ubuntu-20.04 70 | steps: 71 | - uses: actions/checkout@v3 72 | - name: Check formatting 73 | uses: FreeRTOS/CI-CD-Github-Actions/formatting@main 74 | with: 75 | path: ./ 76 | 77 | git-secrets: 78 | runs-on: ubuntu-latest 79 | steps: 80 | - uses: actions/checkout@v3 81 | - name: Checkout awslabs/git-secrets 82 | uses: actions/checkout@v3 83 | with: 84 | repository: awslabs/git-secrets 85 | ref: master 86 | path: git-secrets 87 | - name: Install git-secrets 88 | run: cd git-secrets && sudo make install && cd .. 89 | - name: Run git-secrets 90 | run: | 91 | git-secrets --register-aws 92 | git-secrets --scan 93 | 94 | custom-standard-c-headers: 95 | runs-on: ubuntu-latest 96 | steps: 97 | - name: Clone This Repo 98 | uses: actions/checkout@v3 99 | - name: Build 100 | run: | 101 | mkdir -p override-include 102 | cp source/include/stdbool.readme override-include/stdbool.h 103 | cp source/include/stdint.readme override-include/stdint.h 104 | cmake -S test -B build/ \ 105 | -G "Unix Makefiles" \ 106 | -DBUILD_CLONE_SUBMODULES=ON \ 107 | -DCMAKE_C_FLAGS='-Wall -Wextra -I../override-include' 108 | make -C build/ coverity_analysis 109 | 110 | memory_statistics: 111 | runs-on: ubuntu-latest 112 | steps: 113 | - uses: actions/checkout@v3 114 | with: 115 | submodules: "recursive" 116 | - name: Install Python3 117 | uses: actions/setup-python@v3 118 | with: 119 | python-version: "3.11.0" 120 | - name: Measure sizes 121 | uses: FreeRTOS/CI-CD-Github-Actions/memory_statistics@main 122 | with: 123 | config: .github/memory_statistics_config.json 124 | check_against: docs/doxygen/include/size_table.md 125 | 126 | link-verifier: 127 | runs-on: ubuntu-latest 128 | steps: 129 | - uses: actions/checkout@v3 130 | - name: Check Links 131 | env: 132 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 133 | uses: FreeRTOS/CI-CD-Github-Actions/link-verifier@main 134 | with: 135 | path: ./ 136 | 137 | verify-manifest: 138 | runs-on: ubuntu-latest 139 | steps: 140 | - uses: actions/checkout@v3 141 | with: 142 | submodules: true 143 | fetch-depth: 0 144 | 145 | # At time of writing the gitmodules are set not to pull 146 | # Even when using fetch submodules. Need to run this command 147 | # To force it to grab them. 148 | - name: Perform Recursive Clone 149 | shell: bash 150 | run: git submodule update --checkout --init --recursive 151 | 152 | - name: Run manifest verifier 153 | uses: FreeRTOS/CI-CD-GitHub-Actions/manifest-verifier@main 154 | with: 155 | path: ./ 156 | fail-on-incorrect-version: true 157 | 158 | proof_ci: 159 | if: ${{ github.event.pull_request }} 160 | runs-on: cbmc_ubuntu-latest_64-core 161 | steps: 162 | - name: Set up CBMC runner 163 | uses: FreeRTOS/CI-CD-Github-Actions/set_up_cbmc_runner@main 164 | with: 165 | cadical_tag: "latest" 166 | kissat_tag: "latest" 167 | cbmc_version: "6.3.1" 168 | - name: Run CBMC 169 | uses: FreeRTOS/CI-CD-Github-Actions/run_cbmc@main 170 | with: 171 | proofs_dir: test/cbmc/proofs 172 | run_cbmc_proofs_command: cd ../../../; git apply -v loop_invariants.patch; cd test/cbmc/proofs; ./run-cbmc-proofs.py 173 | -------------------------------------------------------------------------------- /.github/workflows/doxygen.yml: -------------------------------------------------------------------------------- 1 | name: Doxygen Generation 2 | on: 3 | push: 4 | branches: [main] 5 | workflow_dispatch: 6 | jobs: 7 | doxygen-generation: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Doxygen generation 11 | uses: FreeRTOS/CI-CD-Github-Actions/doxygen-generation@main 12 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release automation 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | commit_id: 7 | description: 'Commit ID to tag and create a release for' 8 | required: true 9 | version_number: 10 | description: 'Release Version Number (Eg, v1.0.0)' 11 | required: true 12 | 13 | jobs: 14 | tag-commit: 15 | name: Tag commit 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Checkout code 19 | uses: actions/checkout@v4 20 | with: 21 | ref: ${{ github.event.inputs.commit_id }} 22 | - name: Configure git identity 23 | run: | 24 | git config --global user.name ${{ github.actor }} 25 | git config --global user.email ${{ github.actor }}@users.noreply.github.com 26 | - name: create a new branch that references commit id 27 | env: 28 | VERSION_NUMBER: ${{ github.event.inputs.version_number }} 29 | COMMIT_ID: ${{ github.event.inputs.commit_id }} 30 | run: git checkout -b "$VERSION_NUMBER" "$COMMIT_ID" 31 | - name: Generate SBOM 32 | uses: FreeRTOS/CI-CD-Github-Actions/sbom-generator@main 33 | with: 34 | repo_path: ./ 35 | source_path: ./source 36 | - name: commit SBOM file 37 | env: 38 | VERSION_NUMBER: ${{ github.event.inputs.version_number }} 39 | run: | 40 | git add . 41 | git commit -m 'Update SBOM' 42 | git push -u origin "$VERSION_NUMBER" 43 | - name: Tag Commit and Push to remote 44 | env: 45 | VERSION_NUMBER: ${{ github.event.inputs.version_number }} 46 | run: | 47 | git tag "$VERSION_NUMBER" -a -m "coreJSON Library $VERSION_NUMBER" 48 | git push origin --tags 49 | - name: Verify tag on remote 50 | env: 51 | VERSION_NUMBER: ${{ github.event.inputs.version_number }} 52 | COMMIT_ID: ${{ github.event.inputs.commit_id }} 53 | run: | 54 | git tag -d "$VERSION_NUMBER" 55 | git remote update 56 | git checkout tags/"$VERSION_NUMBER" 57 | git diff "$COMMIT_ID" tags/"$VERSION_NUMBER" 58 | create-zip: 59 | needs: tag-commit 60 | name: Create ZIP and verify package for release asset. 61 | runs-on: ubuntu-latest 62 | steps: 63 | - name: Install ZIP tools 64 | run: sudo apt-get install zip unzip 65 | - name: Checkout code 66 | uses: actions/checkout@v4 67 | with: 68 | ref: ${{ github.event.inputs.commit_id }} 69 | path: coreJSON 70 | submodules: recursive 71 | - name: Checkout disabled submodules 72 | run: | 73 | cd coreJSON 74 | git submodule update --init --checkout --recursive 75 | - name: Create ZIP 76 | env: 77 | VERSION_NUMBER: ${{ github.event.inputs.version_number }} 78 | run: | 79 | zip -r coreJSON-"$VERSION_NUMBER".zip coreJSON -x "*.git*" 80 | ls ./ 81 | - name: Validate created ZIP 82 | env: 83 | VERSION_NUMBER: ${{ github.event.inputs.version_number }} 84 | run: | 85 | mkdir zip-check 86 | mv coreJSON-"$VERSION_NUMBER".zip zip-check 87 | cd zip-check 88 | unzip coreJSON-"$VERSION_NUMBER".zip -d coreJSON-"$VERSION_NUMBER" 89 | ls coreJSON-"$VERSION_NUMBER" 90 | diff -r -x "*.git*" coreJSON-"$VERSION_NUMBER"/coreJSON/ ../coreJSON/ 91 | cd ../ 92 | - name: Build 93 | env: 94 | VERSION_NUMBER: ${{ github.event.inputs.version_number }} 95 | run: | 96 | cd zip-check/coreJSON-"$VERSION_NUMBER"/coreJSON 97 | sudo apt-get install -y lcov 98 | cmake -S test -B build/ \ 99 | -G "Unix Makefiles" \ 100 | -DCMAKE_BUILD_TYPE=Debug \ 101 | -DBUILD_CLONE_SUBMODULES=ON \ 102 | -DCMAKE_C_FLAGS='--coverage -Wall -Wextra -Werror' 103 | make -C build/ all 104 | - name: Test 105 | env: 106 | VERSION_NUMBER: ${{ github.event.inputs.version_number }} 107 | run: | 108 | cd zip-check/coreJSON-"$VERSION_NUMBER"/coreJSON/build/ 109 | ctest -E system --output-on-failure 110 | cd .. 111 | - name: Create artifact of ZIP 112 | uses: actions/upload-artifact@v4 113 | with: 114 | name: coreJSON-${{ github.event.inputs.version_number }}.zip 115 | path: zip-check/coreJSON-${{ github.event.inputs.version_number }}.zip 116 | deploy-doxygen: 117 | needs: tag-commit 118 | name: Deploy doxygen documentation 119 | runs-on: ubuntu-latest 120 | steps: 121 | - name: Doxygen generation 122 | uses: FreeRTOS/CI-CD-Github-Actions/doxygen-generation@main 123 | with: 124 | ref: ${{ github.event.inputs.version_number }} 125 | add_release: "true" 126 | create-release: 127 | needs: 128 | - create-zip 129 | - deploy-doxygen 130 | name: Create Release and Upload Release Asset 131 | runs-on: ubuntu-latest 132 | steps: 133 | - name: Create Release 134 | id: create_release 135 | uses: actions/create-release@v1 136 | env: 137 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 138 | with: 139 | tag_name: ${{ github.event.inputs.version_number }} 140 | release_name: ${{ github.event.inputs.version_number }} 141 | body: Release ${{ github.event.inputs.version_number }} of the coreJSON Library. 142 | draft: false 143 | prerelease: false 144 | - name: Download ZIP artifact 145 | uses: actions/download-artifact@v4 146 | with: 147 | name: coreJSON-${{ github.event.inputs.version_number }}.zip 148 | - name: Upload Release Asset 149 | id: upload-release-asset 150 | uses: actions/upload-release-asset@v1 151 | env: 152 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 153 | with: 154 | upload_url: ${{ steps.create_release.outputs.upload_url }} 155 | asset_path: ./coreJSON-${{ github.event.inputs.version_number }}.zip 156 | asset_name: coreJSON-${{ github.event.inputs.version_number }}.zip 157 | asset_content_type: application/zip 158 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore documentation output. 2 | **/docs/**/output/* 3 | 4 | # Ignore CMake build directory. 5 | build/ 6 | 7 | # Ignore build artifacts 8 | *.o 9 | 10 | # Ignore code coverage artifacts 11 | *.gcda 12 | *.gcno 13 | *.gcov 14 | 15 | # Ignore macOS artifacts 16 | .DS_Store 17 | 18 | # Ignore IDE artifacts 19 | .vscode/ 20 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "test/unit-test/Unity"] 2 | path = test/unit-test/Unity 3 | url = https://github.com/ThrowTheSwitch/Unity 4 | update = none 5 | -------------------------------------------------------------------------------- /.lgtm.yml: -------------------------------------------------------------------------------- 1 | path_classifiers: 2 | library: 3 | - exclude: / 4 | extraction: 5 | cpp: 6 | index: 7 | build_command: 8 | - export 'CFLAGS=-Iinclude -ansi -Wall -Wextra -Wpedantic -Werror' 9 | - make -C source core_json.o 10 | 11 | csharp: 12 | after_prepare: 13 | - false 14 | go: 15 | after_prepare: 16 | - false 17 | java: 18 | after_prepare: 19 | - false 20 | javascript: 21 | after_prepare: 22 | - false 23 | python: 24 | after_prepare: 25 | - false 26 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log for coreJSON Library 2 | 3 | ## v3.3.0 (May 2024) 4 | - [#157](https://github.com/FreeRTOS/coreJSON/pull/157) MISRA C:2012 compliance check. 5 | - [#154](https://github.com/FreeRTOS/coreJSON/pull/154) Add ClusterFuzzLite setup. 6 | - [#144](https://github.com/FreeRTOS/coreJSON/pull/144) Upgrade to CBMC Starter Kit 2.10. 7 | - [#134](https://github.com/FreeRTOS/coreJSON/pull/134) Update doxygen version for documentation. 8 | - [#133](https://github.com/FreeRTOS/coreJSON/pull/133) Update Memory safety proofs to use function contracts. 9 | 10 | ## v3.2.0 (October 2022) 11 | - [#121](https://github.com/FreeRTOS/coreJSON/pull/121) MISRA C:2012 compliance updates. 12 | - [#119](https://github.com/FreeRTOS/coreJSON/pull/119) Update CBMC Starter Kit. 13 | - [#115](https://github.com/FreeRTOS/coreJSON/pull/115) Fix JSON validation for mismatched brackets. 14 | - [#109](https://github.com/FreeRTOS/coreJSON/pull/109) Remove non-ASCII characters 15 | 16 | ## v3.1.0 (November 2021) 17 | - [#106](https://github.com/FreeRTOS/coreJSON/pull/106) Update doxygen version for documentation. 18 | 19 | ## v3.0.2 (July 2021) 20 | - [#100](https://github.com/FreeRTOS/coreJSON/pull/100) Fix overflow in skipOneHexEscape(). 21 | - [#95](https://github.com/FreeRTOS/coreJSON/pull/95) Eliminate warnings when base char type is unsigned. 22 | - [#93](https://github.com/FreeRTOS/coreJSON/pull/93) Wrap query key separator macro with ifndef. 23 | 24 | ## v3.0.1 (February 2021) 25 | - [#86](https://github.com/FreeRTOS/coreJSON/pull/86) Fix MISRA 9.1 violation. 26 | - [#84](https://github.com/FreeRTOS/coreJSON/pull/84), [#82](https://github.com/FreeRTOS/coreJSON/pull/82) and [#80](https://github.com/FreeRTOS/coreJSON/pull/80) Documentation updates and fixes. 27 | 28 | ## v3.0.0 (December 2020) 29 | - [#74](https://github.com/FreeRTOS/coreJSON/pull/74) Add `JSON_Iterate` function to iterate over items in a JSON collection. 30 | - [#74](https://github.com/FreeRTOS/coreJSON/pull/74) Add `JSONInvalid` enum with the value 0 to `JSONTypes_t`. This change is not backwards compatible. 31 | 32 | ## v2.0.0 (November 2020) 33 | 34 | ### Updates 35 | - [#53](https://github.com/FreeRTOS/coreJSON/pull/53) Update the `JSON_Search` function to support searching JSON arrays. This change is not backwards compatible. 36 | 37 | ### Other 38 | - [#35](https://github.com/FreeRTOS/coreJSON/pull/35), [#36](https://github.com/FreeRTOS/coreJSON/pull/36), [#39](https://github.com/FreeRTOS/coreJSON/pull/39), [#51](https://github.com/FreeRTOS/coreJSON/pull/51), [#52](https://github.com/FreeRTOS/coreJSON/pull/52), [#54](https://github.com/FreeRTOS/coreJSON/pull/54) Minor documentation updates. 39 | - [#40](https://github.com/FreeRTOS/coreJSON/pull/40) Build the unit tests with Unity instead of CMock. 40 | - [#44](https://github.com/FreeRTOS/coreJSON/pull/44) Add 100% branch coverage to the unit tests. 41 | - [#46](https://github.com/FreeRTOS/coreJSON/pull/46), [#49](https://github.com/FreeRTOS/coreJSON/pull/49) Fix warnings in the source code. 42 | 43 | ## v1.0.0 (September 2020) 44 | 45 | This is the first release of the coreJSON library, a parser that strictly enforces the [ECMA-404 JSON standard](https://www.json.org/json-en.html) and is suitable for low memory footprint embedded devices. 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /MISRA.md: -------------------------------------------------------------------------------- 1 | # MISRA Compliance 2 | 3 | The coreJSON library files conform to the [MISRA C:2012](https://www.misra.org.uk) 4 | guidelines, with some noted exceptions. Compliance is checked with Coverity static analysis. 5 | The specific deviations, suppressed inline, are listed below. 6 | 7 | Additionally, [MISRA configuration file](https://github.com/FreeRTOS/coreJSON/blob/main/tools/coverity/misra.config) contains the project wide deviations. 8 | 9 | ### Suppressed with Coverity Comments 10 | To find the violation references in the source files run grep on the source code 11 | with ( Assuming rule 11.3 violation; with justification in point 1 ): 12 | ``` 13 | grep 'MISRA Ref 11.3.1' . -rI 14 | ``` 15 | 16 | #### Rule 11.3 17 | _Ref 11.3.1_ 18 | 19 | - MISRA C-2012 Rule 11.3 prohibits casting a pointer to a different type. 20 | This instance is a false positive, as the rule permits the 21 | addition of a const type qualifier. 22 | 23 | #### Rule 14.3 24 | _Ref 14.3.1_ 25 | 26 | - MISRA C-2012 Rule 14.3 False positive as the static analysis tool believes 27 | i can never be larger than SIZE_MAX - HEX_ESCAPE_LENGTH. This can be proven as 28 | a bug by setting i to be 18446744073709551615UL at initial assignment, then require 29 | start != NULL before assigning the value of i to start. This creates a case 30 | where i should be large enough to hit the else statement, but the tool still flags 31 | this as invariant. 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## coreJSON Library 2 | 3 | **[API Documentation Pages for current and previous releases of this library can be found here](https://freertos.github.io/coreJSON/)** 4 | 5 | This repository contains the coreJSON library, a parser that strictly enforces 6 | the ECMA-404 JSON standard and is suitable for low memory footprint embedded 7 | devices. The coreJSON library is distributed under the 8 | [MIT Open Source License](LICENSE). 9 | 10 | This library has gone through code quality checks including verification that no 11 | function has a 12 | [GNU Complexity](https://www.gnu.org/software/complexity/manual/complexity.html) 13 | score over 8, and checks against deviations from mandatory rules in the 14 | [MISRA coding standard](https://www.misra.org.uk). Deviations from the MISRA 15 | C:2012 guidelines are documented under [MISRA Deviations](MISRA.md). This 16 | library has also undergone both static code analysis from 17 | [Coverity static analysis](https://scan.coverity.com/), and validation of memory 18 | safety through the 19 | [CBMC automated reasoning tool](https://www.cprover.org/cbmc/). 20 | 21 | See memory requirements for this library 22 | [here](./docs/doxygen/include/size_table.md). 23 | 24 | **coreJSON v3.3.0 25 | [source code](https://github.com/FreeRTOS/coreJSON/tree/v3.3.0/source) is part 26 | of the 27 | [FreeRTOS 202406.00 LTS](https://github.com/FreeRTOS/FreeRTOS-LTS/tree/202406.00-LTS) 28 | release.** 29 | 30 | ## Reference example 31 | 32 | ```c 33 | #include 34 | #include "core_json.h" 35 | 36 | int main() 37 | { 38 | // Variables used in this example. 39 | JSONStatus_t result; 40 | char buffer[] = "{\"foo\":\"abc\",\"bar\":{\"foo\":\"xyz\"}}"; 41 | size_t bufferLength = sizeof( buffer ) - 1; 42 | char queryKey[] = "bar.foo"; 43 | size_t queryKeyLength = sizeof( queryKey ) - 1; 44 | char * value; 45 | size_t valueLength; 46 | 47 | // Calling JSON_Validate() is not necessary if the document is guaranteed to be valid. 48 | result = JSON_Validate( buffer, bufferLength ); 49 | 50 | if( result == JSONSuccess ) 51 | { 52 | result = JSON_Search( buffer, bufferLength, queryKey, queryKeyLength, 53 | &value, &valueLength ); 54 | } 55 | 56 | if( result == JSONSuccess ) 57 | { 58 | // The pointer "value" will point to a location in the "buffer". 59 | char save = value[ valueLength ]; 60 | // After saving the character, set it to a null byte for printing. 61 | value[ valueLength ] = '\0'; 62 | // "Found: bar.foo -> xyz" will be printed. 63 | printf( "Found: %s -> %s\n", queryKey, value ); 64 | // Restore the original character. 65 | value[ valueLength ] = save; 66 | } 67 | 68 | return 0; 69 | } 70 | ``` 71 | 72 | A search may descend through nested objects when the `queryKey` contains 73 | matching key strings joined by a separator, `.`. In the example above, `bar` has 74 | the value `{"foo":"xyz"}`. Therefore, a search for query key `bar.foo` would 75 | output `xyz`. 76 | 77 | ## Building coreJSON 78 | 79 | A compiler that supports **C90 or later** such as _gcc_ is required to build the 80 | library. 81 | 82 | Additionally, the library uses 2 header files introduced in ISO C99, `stdbool.h` 83 | and `stdint.h`. For compilers that do not provide this header file, the 84 | [source/include](source/include) directory contains 85 | [stdbool.readme](source/include/stdbool.readme) and 86 | [stdint.readme](source/include/stdint.readme), which can be renamed to 87 | `stdbool.h` and `stdint.h` respectively. 88 | 89 | For instance, if the example above is copied to a file named `example.c`, _gcc_ 90 | can be used like so: 91 | 92 | ```bash 93 | gcc -I source/include example.c source/core_json.c -o example 94 | ./example 95 | ``` 96 | 97 | _gcc_ can also produce an output file to be linked: 98 | 99 | ```bash 100 | gcc -I source/include -c source/core_json.c 101 | ``` 102 | 103 | ## Documentation 104 | 105 | ### Existing documentation 106 | 107 | For pre-generated documentation, please see the documentation linked in the 108 | locations below: 109 | 110 | | Location | 111 | | :------------------------------------------------------------------------------------------------------------------: | 112 | | [AWS IoT Device SDK for Embedded C](https://github.com/aws/aws-iot-device-sdk-embedded-C#releases-and-documentation) | 113 | | [GitHub.io](https://freertos.github.io/coreJSON/v3.3.0/) | 114 | 115 | Note that the latest included version of the coreJSON library may differ across 116 | repositories. 117 | 118 | ### Generating documentation 119 | 120 | The Doxygen references were created using Doxygen version 1.9.6. To generate the 121 | Doxygen pages, please run the following command from the root of this 122 | repository: 123 | 124 | ```shell 125 | doxygen docs/doxygen/config.doxyfile 126 | ``` 127 | 128 | ## Building unit tests 129 | 130 | ### Checkout Unity Submodule 131 | 132 | By default, the submodules in this repository are configured with `update=none` 133 | in [.gitmodules](.gitmodules), to avoid increasing clone time and disk space 134 | usage of other repositories (like 135 | [amazon-freertos](https://github.com/aws/amazon-freertos) that submodules this 136 | repository). 137 | 138 | To build unit tests, the submodule dependency of Unity is required. Use the 139 | following command to clone the submodule: 140 | 141 | ``` 142 | git submodule update --checkout --init --recursive test/unit-test/Unity 143 | ``` 144 | 145 | ### Platform Prerequisites 146 | 147 | - For running unit tests 148 | - C90 compiler like gcc 149 | - CMake 3.13.0 or later 150 | - Ruby 2.0.0 or later is additionally required for the Unity test framework 151 | (that we use). 152 | - For running the coverage target, gcov is additionally required. 153 | 154 | ### Steps to build Unit Tests 155 | 156 | 1. Go to the root directory of this repository. (Make sure that the **Unity** 157 | submodule is cloned as described [above](#checkout-unity-submodule).) 158 | 159 | 1. Create build directory: `mkdir build && cd build` 160 | 161 | 1. Run _cmake_ while inside build directory: `cmake -S ../test` 162 | 163 | 1. Run this command to build the library and unit tests: `make all` 164 | 165 | 1. The generated test executables will be present in `build/bin/tests` folder. 166 | 167 | 1. Run `ctest` to execute all tests and view the test run summary. 168 | 169 | ## CBMC 170 | 171 | To learn more about CBMC and proofs specifically, review the training material 172 | [here](https://model-checking.github.io/cbmc-training). 173 | 174 | The `test/cbmc/proofs` directory contains CBMC proofs. 175 | 176 | In order to run these proofs you will need to install CBMC and other tools by 177 | following the instructions 178 | [here](https://model-checking.github.io/cbmc-training/installation.html). 179 | 180 | ## Contributing 181 | 182 | See [CONTRIBUTING.md](./.github/CONTRIBUTING.md) for information on 183 | contributing. 184 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | ## Reporting a Vulnerability 2 | 3 | If you discover a potential security issue in this project, we ask that you notify AWS/Amazon Security 4 | via our [vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/) or directly via email to aws-security@amazon.com. 5 | Please do **not** create a public github issue. 6 | -------------------------------------------------------------------------------- /cspell.config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | $schema: https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json 3 | version: '0.2' 4 | # Allows things like stringLength 5 | allowCompoundWords: true 6 | 7 | # Read files not to spell check from the git ignore 8 | useGitignore: true 9 | 10 | # Language settings for C 11 | languageSettings: 12 | - caseSensitive: false 13 | enabled: true 14 | languageId: c 15 | locale: "*" 16 | 17 | # Add a dictionary, and the path to the word list 18 | dictionaryDefinitions: 19 | - name: freertos-words 20 | path: '.github/.cSpellWords.txt' 21 | addWords: true 22 | 23 | dictionaries: 24 | - freertos-words 25 | 26 | # Paths and files to ignore 27 | ignorePaths: 28 | - 'dependency' 29 | - 'docs' 30 | - 'ThirdParty' 31 | - 'History.txt' 32 | -------------------------------------------------------------------------------- /docs/doxygen/include/size_table.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
Code Size of coreJSON (example generated with GCC for ARM Cortex-M)
File
With -O1 Optimization
With -Os Optimization
core_json.c
3.0K
2.5K
Total estimates
3.0K
2.5K
21 | -------------------------------------------------------------------------------- /docs/doxygen/layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /docs/doxygen/pages.dox: -------------------------------------------------------------------------------- 1 | /** 2 | @mainpage Overview 3 | @anchor json 4 | @brief coreJSON Library 5 | 6 |

7 | A parser that supports key lookups while also strictly enforcing the ECMA-404 JSON standard. 8 | The library is written in C and designed to be compliant with ISO C90 and MISRA C. It has proven safe memory use 9 | and no heap allocation, making it suitable for IoT microcontrollers, but also fully portable to other platforms. 10 |

11 | 12 | @section json_memory_requirements Memory Requirements 13 | @brief Memory requirements of the JSON library. 14 | 15 | @include{doc} size_table.md 16 | 17 | @section json_design Design 18 | @brief JSON Library Design 19 | 20 |

Memory Usage

21 |

22 | All functions in the JSON library operate only on the buffers provided and use only 23 | local variables on the stack. In order to support static-only usage, we made a 24 | trade-off to re-parse as necessary so that we would not need to keep state. 25 |

26 | 27 |

Parsing Strictness

28 |

29 | Input validation is necessary for strong security posture. As such, the parser 30 | strictly enforces the ECMA-404 JSON standard. Additionally, JSON documents are 31 | checked for illegal UTF-8 sequences, and strings have unicode hex escapes validated. 32 |

33 | 34 |

Compliance & Coverage

35 |

36 | The JSON library is designed to be compliant with ISO C90 and MISRA C:2012. 37 | All functions are written to have minimal complexity. Unit tests and CBMC proofs 38 | are written to cover every path of execution and achieve 100% branch coverage. 39 |

40 | */ 41 | 42 | /** 43 | @page json_functions Functions 44 | @brief Primary functions of the JSON library:

45 | @subpage json_validate_function
46 | @subpage json_search_function
47 | @subpage json_searcht_function
48 | @subpage json_searchconst_function
49 | @subpage json_iterate_function
50 | 51 | @page json_validate_function JSON_Validate 52 | @snippet core_json.h declare_json_validate 53 | @copydoc JSON_Validate 54 | 55 | @page json_search_function JSON_Search 56 | @snippet core_json.h declare_json_search 57 | @copydoc JSON_Search 58 | 59 | @page json_searcht_function JSON_SearchT 60 | @snippet core_json.h declare_json_searcht 61 | @copydoc JSON_SearchT 62 | 63 | @page json_searchconst_function JSON_SearchConst 64 | @snippet core_json.h declare_json_searchconst 65 | @copydoc JSON_SearchConst 66 | 67 | @page json_iterate_function JSON_Iterate 68 | @snippet core_json.h declare_json_iterate 69 | @copydoc JSON_Iterate 70 | */ 71 | 72 | 73 | /** 74 | @defgroup json_enum_types Enumerated Types 75 | @brief Enumerated types of the JSON library 76 | 77 | @defgroup json_struct_types Struct Types 78 | @brief Struct types of the JSON library 79 | */ 80 | -------------------------------------------------------------------------------- /docs/doxygen/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Stylesheet for Doxygen HTML output. 3 | * 4 | * This file defines styles for custom elements in the header/footer and 5 | * overrides some of the default Doxygen styles. 6 | * 7 | * Styles in this file do not affect the treeview sidebar. 8 | */ 9 | 10 | /* Set the margins to place a small amount of whitespace on the left and right 11 | * side of the page. */ 12 | div.contents { 13 | margin-left:4em; 14 | margin-right:4em; 15 | } 16 | 17 | /* Justify text in paragraphs. */ 18 | p { 19 | text-align: justify; 20 | } 21 | 22 | /* Style of section headings. */ 23 | h1 { 24 | border-bottom: 1px solid #879ECB; 25 | color: #354C7B; 26 | font-size: 160%; 27 | font-weight: normal; 28 | padding-bottom: 4px; 29 | padding-top: 8px; 30 | } 31 | 32 | /* Style of subsection headings. */ 33 | h2:not(.memtitle):not(.groupheader) { 34 | font-size: 125%; 35 | margin-bottom: 0px; 36 | margin-top: 16px; 37 | padding: 0px; 38 | } 39 | 40 | /* Style of paragraphs immediately after subsection headings. */ 41 | h2 + p { 42 | margin: 0px; 43 | padding: 0px; 44 | } 45 | 46 | /* Style of subsection headings. */ 47 | h3 { 48 | font-size: 100%; 49 | margin-bottom: 0px; 50 | margin-left: 2em; 51 | margin-right: 2em; 52 | } 53 | 54 | /* Style of paragraphs immediately after subsubsection headings. */ 55 | h3 + p { 56 | margin-top: 0px; 57 | margin-left: 2em; 58 | margin-right: 2em; 59 | } 60 | 61 | /* Style of the prefix "AWS IoT Device SDK C" that appears in the header. */ 62 | #csdkprefix { 63 | color: #757575; 64 | } 65 | 66 | /* Style of the "Return to main page" link that appears in the header. */ 67 | #returntomain { 68 | padding: 0.5em; 69 | } 70 | 71 | /* Style of the dividers on Configuration Settings pages. */ 72 | div.configpagedivider { 73 | margin-left: 0px !important; 74 | margin-right: 0px !important; 75 | margin-top: 20px !important; 76 | } 77 | 78 | /* Style of configuration setting names. */ 79 | dl.section.user ~ h1 { 80 | border-bottom: none; 81 | color: #000000; 82 | font-family: monospace, fixed; 83 | font-size: 16px; 84 | margin-bottom: 0px; 85 | margin-left: 2em; 86 | margin-top: 1.5em; 87 | } 88 | 89 | /* Style of paragraphs on a configuration settings page. */ 90 | dl.section.user ~ * { 91 | margin-bottom: 10px; 92 | margin-left: 4em; 93 | margin-right: 4em; 94 | margin-top: 0px; 95 | } 96 | 97 | /* Hide the configuration setting marker. */ 98 | dl.section.user { 99 | display: none; 100 | } 101 | 102 | /* Overrides for code fragments and lines. */ 103 | div.fragment { 104 | background: #ffffff; 105 | border: none; 106 | padding: 5px; 107 | } 108 | 109 | div.line { 110 | color: #3a3a3a; 111 | } 112 | 113 | /* Overrides for code syntax highlighting colors. */ 114 | span.comment { 115 | color: #008000; 116 | } 117 | 118 | span.keyword, span.keywordtype, span.keywordflow { 119 | color: #0000ff; 120 | } 121 | 122 | span.preprocessor { 123 | color: #50015a; 124 | } 125 | 126 | span.stringliteral, span.charliteral { 127 | color: #800c0c; 128 | } 129 | 130 | a.code, a.code:visited, a.line, a.line:visited { 131 | color: #496194; 132 | } 133 | -------------------------------------------------------------------------------- /jsonFilePaths.cmake: -------------------------------------------------------------------------------- 1 | # This file is to add source files and include directories 2 | # into variables so that it can be reused from different repositories 3 | # in their Cmake based build system by including this file. 4 | # 5 | # Files specific to the repository such as test runner, platform tests 6 | # are not added to the variables. 7 | 8 | # JSON library source files. 9 | set( JSON_SOURCES 10 | ${CMAKE_CURRENT_LIST_DIR}/source/core_json.c ) 11 | 12 | # JSON library Public Include directories. 13 | set( JSON_INCLUDE_PUBLIC_DIRS 14 | ${CMAKE_CURRENT_LIST_DIR}/source/include ) 15 | -------------------------------------------------------------------------------- /loop_invariants.patch: -------------------------------------------------------------------------------- 1 | diff --git a/source/core_json.c b/source/core_json.c 2 | index d8694f0..761c44b 100644 3 | --- a/source/core_json.c 4 | +++ b/source/core_json.c 5 | @@ -63,6 +63,21 @@ typedef union 6 | #define isCurlyOpen_( x ) ( ( x ) == '{' ) 7 | #define isCurlyClose_( x ) ( ( x ) == '}' ) 8 | 9 | +/** 10 | + * Renaming all loop-contract clauses from CBMC for readability. 11 | + * For more information about loop contracts in CBMC, see 12 | + * https://diffblue.github.io/cbmc/contracts-user.html. 13 | + */ 14 | +#ifdef CBMC 15 | + #define loopInvariant(...) __CPROVER_loop_invariant(__VA_ARGS__) 16 | + #define decreases(...) __CPROVER_decreases(__VA_ARGS__) 17 | + #define assigns(...) __CPROVER_assigns(__VA_ARGS__) 18 | +#else 19 | + #define loopInvariant(...) 20 | + #define decreases(...) 21 | + #define assigns(...) 22 | +#endif 23 | + 24 | /** 25 | * @brief Advance buffer index beyond whitespace. 26 | * 27 | @@ -79,6 +94,9 @@ static void skipSpace( const char * buf, 28 | coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) ); 29 | 30 | for( i = *start; i < max; i++ ) 31 | + assigns( i ) 32 | + loopInvariant( *start <= i && i <= max ) 33 | + decreases( max - i ) 34 | { 35 | if( !isspace_( buf[ i ] ) ) 36 | { 37 | @@ -103,6 +121,13 @@ static size_t countHighBits( uint8_t c ) 38 | size_t i = 0; 39 | 40 | while( ( n & 0x80U ) != 0U ) 41 | + assigns( i, n ) 42 | + loopInvariant ( 43 | + ( 0U <= i ) && ( i <= 8U ) 44 | + && ( n == ( c & ( 0xFF >> i ) ) << i ) 45 | + && ( ( ( c >> ( 8U - i ) ) + 1U ) == ( 1U << i ) ) 46 | + ) 47 | + decreases( 8U - i ) 48 | { 49 | i++; 50 | n = ( n & 0x7FU ) << 1U; 51 | @@ -211,6 +236,13 @@ static bool skipUTF8MultiByte( const char * buf, 52 | /* The bit count is 1 greater than the number of bytes, 53 | * e.g., when j is 2, we skip one more byte. */ 54 | for( j = bitCount - 1U; j > 0U; j-- ) 55 | + assigns( j, i, value, c.c ) 56 | + loopInvariant( 57 | + ( 0 <= j ) && ( j <= bitCount - 1 ) 58 | + && ( *start <= i ) && ( i <= max ) 59 | + && ( ( i == max ) ==> ( j > 0 ) ) 60 | + ) 61 | + decreases( j ) 62 | { 63 | i++; 64 | 65 | @@ -346,6 +378,12 @@ static bool skipOneHexEscape( const char * buf, 66 | if( ( end < max ) && ( buf[ i ] == '\\' ) && ( buf[ i + 1U ] == 'u' ) ) 67 | { 68 | for( i += 2U; i < end; i++ ) 69 | + assigns( value, i ) 70 | + loopInvariant( 71 | + ( *start + 2U <= i ) && ( i <= end ) && 72 | + ( 0U <= value ) && ( value < ( 1U << ( 4U * ( i - ( 2U + *start ) ) ) ) ) 73 | + ) 74 | + decreases( end - i ) 75 | { 76 | uint8_t n = hexToInt( buf[ i ] ); 77 | 78 | @@ -523,6 +561,9 @@ static bool skipString( const char * buf, 79 | i++; 80 | 81 | while( i < max ) 82 | + assigns( i ) 83 | + loopInvariant( *start + 1U <= i && i <= max ) 84 | + decreases( max - i ) 85 | { 86 | if( buf[ i ] == '"' ) 87 | { 88 | @@ -581,6 +622,9 @@ static bool strnEq( const char * a, 89 | coreJSON_ASSERT( ( a != NULL ) && ( b != NULL ) ); 90 | 91 | for( i = 0; i < n; i++ ) 92 | + assigns( i ) 93 | + loopInvariant( i <= n ) 94 | + decreases( n - i ) 95 | { 96 | if( a[ i ] != b[ i ] ) 97 | { 98 | @@ -696,6 +740,9 @@ static bool skipDigits( const char * buf, 99 | saveStart = *start; 100 | 101 | for( i = *start; i < max; i++ ) 102 | + assigns( value, i ) 103 | + loopInvariant( *start <= i && i <= max ) 104 | + decreases( max - i ) 105 | { 106 | if( !isdigit_( buf[ i ] ) ) 107 | { 108 | @@ -945,6 +992,9 @@ static void skipArrayScalars( const char * buf, 109 | i = *start; 110 | 111 | while( i < max ) 112 | + assigns( i ) 113 | + loopInvariant( *start <= i && i <= max ) 114 | + decreases( max - i ) 115 | { 116 | if( skipAnyScalar( buf, &i, max ) != true ) 117 | { 118 | @@ -991,6 +1041,13 @@ static bool skipObjectScalars( const char * buf, 119 | i = *start; 120 | 121 | while( i < max ) 122 | + assigns( i, *start, comma ) 123 | + loopInvariant( 124 | + i >= *start 125 | + && __CPROVER_loop_entry( i ) <= i && i <= max 126 | + && __CPROVER_loop_entry( *start ) <= *start && *start <= max 127 | + ) 128 | + decreases( max - i ) 129 | { 130 | if( skipString( buf, &i, max ) != true ) 131 | { 132 | @@ -1118,6 +1175,14 @@ static JSONStatus_t skipCollection( const char * buf, 133 | i = *start; 134 | 135 | while( i < max ) 136 | + assigns( i, depth, c, __CPROVER_object_whole( stack ), ret ) 137 | + loopInvariant( 138 | + -1 <= depth && depth <= JSON_MAX_DEPTH 139 | + && *start <= i && i <= max 140 | + && ( ( ret == JSONSuccess ) ==> i >= *start + 2U ) 141 | + && ( ret == JSONSuccess || ret == JSONPartial || ret == JSONIllegalDocument || ret == JSONMaxDepthExceeded ) 142 | + ) 143 | + decreases( max - i ) 144 | { 145 | c = buf[ i ]; 146 | i++; 147 | @@ -1407,6 +1472,9 @@ static bool objectSearch( const char * buf, 148 | skipSpace( buf, &i, max ); 149 | 150 | while( i < max ) 151 | + assigns( i, key, keyLength, value, valueLength ) 152 | + loopInvariant( __CPROVER_loop_entry( i ) <= i && i <= max ) 153 | + decreases( max - i ) 154 | { 155 | if( nextKeyValuePair( buf, &i, max, &key, &keyLength, 156 | &value, &valueLength ) != true ) 157 | @@ -1474,6 +1542,9 @@ static bool arraySearch( const char * buf, 158 | skipSpace( buf, &i, max ); 159 | 160 | while( i < max ) 161 | + assigns( i, currentIndex, value, valueLength ) 162 | + loopInvariant( __CPROVER_loop_entry( i ) <= i && i <= max && currentIndex < i ) 163 | + decreases( max - i ) 164 | { 165 | if( nextValue( buf, &i, max, &value, &valueLength ) != true ) 166 | { 167 | @@ -1539,6 +1610,9 @@ static bool skipQueryPart( const char * buf, 168 | while( ( i < max ) && 169 | !isSeparator_( buf[ i ] ) && 170 | !isSquareOpen_( buf[ i ] ) ) 171 | + assigns( i ) 172 | + loopInvariant( i <= max ) 173 | + decreases( max - i ) 174 | { 175 | i++; 176 | } 177 | @@ -1585,6 +1659,17 @@ static JSONStatus_t multiSearch( const char * buf, 178 | coreJSON_ASSERT( ( max > 0U ) && ( queryLength > 0U ) ); 179 | 180 | while( i < queryLength ) 181 | + assigns( i, start, queryStart, value, length ) 182 | + loopInvariant( 183 | + 0U <= start && start < max 184 | + && 0U < length && length <= max 185 | + && start + length <= max 186 | + && ( ( i == queryLength && ret == JSONSuccess && buf[ start ] == '"' ) ==> length >= 2U ) 187 | + && 0U <= value && value < max 188 | + && 0U <= i && i <= queryLength 189 | + && 0U <= queryStart && queryStart <= queryLength 190 | + ) 191 | + decreases( queryLength - i ) 192 | { 193 | bool found = false; 194 | 195 | -------------------------------------------------------------------------------- /manifest.yml: -------------------------------------------------------------------------------- 1 | name : "coreJSON" 2 | version: "v3.3.0" 3 | description: | 4 | "A parser strictly enforcing the ECMA-404 JSON standard, suitable for microcontrollers. \n" 5 | license: "MIT" 6 | 7 | dependencies: 8 | - name: "Unity" 9 | version: v2.6.0 10 | license: "MIT" 11 | repository: 12 | type: "git" 13 | url: "https://github.com/ThrowTheSwitch/Unity.git" 14 | path: test/unit-test/Unity 15 | -------------------------------------------------------------------------------- /source/include/core_json.h: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file core_json.h 27 | * @brief Include this header file to use coreJSON in your application. 28 | */ 29 | 30 | #ifndef CORE_JSON_H_ 31 | #define CORE_JSON_H_ 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | /* *INDENT-OFF* */ 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | /* *INDENT-ON* */ 42 | 43 | /** 44 | * @brief By default, has the stand behavior of assert() for 45 | * parameter checking. To swap out the assert(), define this 46 | * macro with the desired behavior. */ 47 | #ifndef coreJSON_ASSERT 48 | #define coreJSON_ASSERT( expr ) assert( expr ) 49 | #endif 50 | 51 | 52 | /** 53 | * @ingroup json_enum_types 54 | * @brief Return codes from coreJSON library functions. 55 | */ 56 | typedef enum 57 | { 58 | JSONPartial = 0, /**< @brief JSON document is valid so far but incomplete. */ 59 | JSONSuccess, /**< @brief JSON document is valid and complete. */ 60 | JSONIllegalDocument, /**< @brief JSON document is invalid or malformed. */ 61 | JSONMaxDepthExceeded, /**< @brief JSON document has nesting that exceeds JSON_MAX_DEPTH. */ 62 | JSONNotFound, /**< @brief Query key could not be found in the JSON document. */ 63 | JSONNullParameter, /**< @brief Pointer parameter passed to a function is NULL. */ 64 | JSONBadParameter /**< @brief Query key is empty, or any subpart is empty, or max is 0. */ 65 | } JSONStatus_t; 66 | 67 | /** 68 | * @brief Parse a buffer to determine if it contains a valid JSON document. 69 | * 70 | * @param[in] buf The buffer to parse. 71 | * @param[in] max The size of the buffer. 72 | * 73 | * @note The maximum nesting depth may be specified by defining the macro 74 | * JSON_MAX_DEPTH. The default is 32 of sizeof(char). 75 | * 76 | * @note By default, a valid JSON document may contain a single element 77 | * (e.g., string, boolean, number). To require that a valid document 78 | * contain an object or array, define JSON_VALIDATE_COLLECTIONS_ONLY. 79 | * 80 | * @return #JSONSuccess if the buffer contents are valid JSON; 81 | * #JSONNullParameter if buf is NULL; 82 | * #JSONBadParameter if max is 0; 83 | * #JSONIllegalDocument if the buffer contents are NOT valid JSON; 84 | * #JSONMaxDepthExceeded if object and array nesting exceeds a threshold; 85 | * #JSONPartial if the buffer contents are potentially valid but incomplete. 86 | * 87 | * Example 88 | * @code{c} 89 | * // Variables used in this example. 90 | * JSONStatus_t result; 91 | * char buffer[] = "{\"foo\":\"abc\",\"bar\":{\"foo\":\"xyz\"}}"; 92 | * size_t bufferLength = sizeof( buffer ) - 1; 93 | * 94 | * result = JSON_Validate( buffer, bufferLength ); 95 | * 96 | * // JSON document is valid. 97 | * assert( result == JSONSuccess ); 98 | * @endcode 99 | */ 100 | /* @[declare_json_validate] */ 101 | JSONStatus_t JSON_Validate( const char * buf, 102 | size_t max ); 103 | /* @[declare_json_validate] */ 104 | 105 | /** 106 | * @brief Find a key or array index in a JSON document and output the 107 | * pointer @p outValue to its value. 108 | * 109 | * Any value may also be an object or an array to a maximum depth. A search 110 | * may descend through nested objects or arrays when the query contains matching 111 | * key strings or array indexes joined by a separator. 112 | * 113 | * For example, if the provided buffer contains {"foo":"abc","bar":{"foo":"xyz"}}, 114 | * then a search for 'foo' would output abc, 'bar' would output 115 | * {"foo":"xyz"}, and a search for 'bar.foo' would output 116 | * xyz. 117 | * 118 | * If the provided buffer contains [123,456,{"foo":"abc","bar":[88,99]}], 119 | * then a search for '[1]' would output 456, '[2].foo' would output 120 | * abc, and '[2].bar[0]' would output 88. 121 | * 122 | * On success, the pointer @p outValue points to a location in buf. No null 123 | * termination is done for the value. For valid JSON it is safe to place 124 | * a null character at the end of the value, so long as the character 125 | * replaced is put back before running another search. 126 | * 127 | * @param[in] buf The buffer to search. 128 | * @param[in] max size of the buffer. 129 | * @param[in] query The object keys and array indexes to search for. 130 | * @param[in] queryLength Length of the key. 131 | * @param[out] outValue A pointer to receive the address of the value found. 132 | * @param[out] outValueLength A pointer to receive the length of the value found. 133 | * 134 | * @note The maximum nesting depth may be specified by defining the macro 135 | * JSON_MAX_DEPTH. The default is 32 of sizeof(char). 136 | * 137 | * @note JSON_Search() performs validation, but stops upon finding a matching 138 | * key and its value. To validate the entire JSON document, use JSON_Validate(). 139 | * 140 | * @return #JSONSuccess if the query is matched and the value output; 141 | * #JSONNullParameter if any pointer parameters are NULL; 142 | * #JSONBadParameter if the query is empty, or the portion after a separator is empty, 143 | * or max is 0, or an index is too large to convert to a signed 32-bit integer; 144 | * #JSONNotFound if the query has no match. 145 | * 146 | * Example 147 | * @code{c} 148 | * // Variables used in this example. 149 | * JSONStatus_t result; 150 | * char buffer[] = "{\"foo\":\"abc\",\"bar\":{\"foo\":\"xyz\"}}"; 151 | * size_t bufferLength = sizeof( buffer ) - 1; 152 | * char query[] = "bar.foo"; 153 | * size_t queryLength = sizeof( query ) - 1; 154 | * char * value; 155 | * size_t valueLength; 156 | * 157 | * // Calling JSON_Validate() is not necessary if the document is guaranteed to be valid. 158 | * result = JSON_Validate( buffer, bufferLength ); 159 | * 160 | * if( result == JSONSuccess ) 161 | * { 162 | * result = JSON_Search( buffer, bufferLength, query, queryLength, 163 | * &value, &valueLength ); 164 | * } 165 | * 166 | * if( result == JSONSuccess ) 167 | * { 168 | * // The pointer "value" will point to a location in the "buffer". 169 | * char save = value[ valueLength ]; 170 | * // After saving the character, set it to a null byte for printing. 171 | * value[ valueLength ] = '\0'; 172 | * // "Found: bar.foo -> xyz" will be printed. 173 | * printf( "Found: %s -> %s\n", query, value ); 174 | * // Restore the original character. 175 | * value[ valueLength ] = save; 176 | * } 177 | * @endcode 178 | * 179 | * @note The maximum index value is ~2 billion ( 2^31 - 9 ). 180 | */ 181 | /* @[declare_json_search] */ 182 | #define JSON_Search( buf, max, query, queryLength, outValue, outValueLength ) \ 183 | JSON_SearchT( buf, max, query, queryLength, outValue, outValueLength, NULL ) 184 | /* @[declare_json_search] */ 185 | 186 | /** 187 | * @brief The largest value usable as an array index in a query 188 | * for JSON_Search(), ~2 billion. 189 | */ 190 | #define MAX_INDEX_VALUE ( 0x7FFFFFF7 ) /* 2^31 - 9 */ 191 | 192 | /** 193 | * @ingroup json_enum_types 194 | * @brief Value types from the JSON standard. 195 | */ 196 | typedef enum 197 | { 198 | JSONInvalid = 0, /**< @brief Not a valid JSON type. */ 199 | JSONString, /**< @brief A quote delimited sequence of Unicode characters. */ 200 | JSONNumber, /**< @brief A rational number. */ 201 | JSONTrue, /**< @brief The literal value true. */ 202 | JSONFalse, /**< @brief The literal value false. */ 203 | JSONNull, /**< @brief The literal value null. */ 204 | JSONObject, /**< @brief A collection of zero or more key-value pairs. */ 205 | JSONArray /**< @brief A collection of zero or more values. */ 206 | } JSONTypes_t; 207 | 208 | /** 209 | * @brief Same as JSON_Search(), but also outputs a type for the value found 210 | * 211 | * See @ref JSON_Search for documentation of common behavior. 212 | * 213 | * @param[in] buf The buffer to search. 214 | * @param[in] max size of the buffer. 215 | * @param[in] query The object keys and array indexes to search for. 216 | * @param[in] queryLength Length of the key. 217 | * @param[out] outValue A pointer to receive the address of the value found. 218 | * @param[out] outValueLength A pointer to receive the length of the value found. 219 | * @param[out] outType An enum indicating the JSON-specific type of the value. 220 | */ 221 | /* @[declare_json_searcht] */ 222 | JSONStatus_t JSON_SearchT( char * buf, 223 | size_t max, 224 | const char * query, 225 | size_t queryLength, 226 | char ** outValue, 227 | size_t * outValueLength, 228 | JSONTypes_t * outType ); 229 | /* @[declare_json_searcht] */ 230 | 231 | /** 232 | * @brief Same as JSON_SearchT(), but with const qualified buf and outValue arguments. 233 | * 234 | * See @ref JSON_Search for documentation of common behavior. 235 | * 236 | * @param[in] buf The buffer to search. 237 | * @param[in] max size of the buffer. 238 | * @param[in] query The object keys and array indexes to search for. 239 | * @param[in] queryLength Length of the key. 240 | * @param[out] outValue A pointer to receive the address of the value found. 241 | * @param[out] outValueLength A pointer to receive the length of the value found. 242 | * @param[out] outType An enum indicating the JSON-specific type of the value. 243 | */ 244 | /* @[declare_json_searchconst] */ 245 | JSONStatus_t JSON_SearchConst( const char * buf, 246 | size_t max, 247 | const char * query, 248 | size_t queryLength, 249 | const char ** outValue, 250 | size_t * outValueLength, 251 | JSONTypes_t * outType ); 252 | /* @[declare_json_searchconst] */ 253 | 254 | /** 255 | * @ingroup json_struct_types 256 | * @brief Structure to represent a key-value pair. 257 | */ 258 | typedef struct 259 | { 260 | const char * key; /**< @brief Pointer to the code point sequence for key. */ 261 | size_t keyLength; /**< @brief Length of the code point sequence for key. */ 262 | const char * value; /**< @brief Pointer to the code point sequence for value. */ 263 | size_t valueLength; /**< @brief Length of the code point sequence for value. */ 264 | JSONTypes_t jsonType; /**< @brief JSON-specific type of the value. */ 265 | } JSONPair_t; 266 | 267 | /** 268 | * @brief Output the next key-value pair or value from a collection. 269 | * 270 | * This function may be used in a loop to output each key-value pair from an object, 271 | * or each value from an array. For the first invocation, the integers pointed to by 272 | * start and next should be initialized to 0. These will be updated by the function. 273 | * If another key-value pair or value is present, the output structure is populated 274 | * and #JSONSuccess is returned; otherwise the structure is unchanged and #JSONNotFound 275 | * is returned. 276 | * 277 | * @param[in] buf The buffer to search. 278 | * @param[in] max size of the buffer. 279 | * @param[in,out] start The index at which the collection begins. 280 | * @param[in,out] next The index at which to seek the next value. 281 | * @param[out] outPair A pointer to receive the next key-value pair. 282 | * 283 | * @note This function expects a valid JSON document; run JSON_Validate() first. 284 | * 285 | * @note For an object, the outPair structure will reference a key and its value. 286 | * For an array, only the value will be referenced (i.e., outPair.key will be NULL). 287 | * 288 | * @return #JSONSuccess if a value is output; 289 | * #JSONIllegalDocument if the buffer does not contain a collection; 290 | * #JSONNotFound if there are no further values in the collection. 291 | * 292 | * Example 293 | * @code{c} 294 | * // Variables used in this example. 295 | * static char * json_types[] = 296 | * { 297 | * "invalid", 298 | * "string", 299 | * "number", 300 | * "true", 301 | * "false", 302 | * "null", 303 | * "object", 304 | * "array" 305 | * }; 306 | * 307 | * void show( const char * json, 308 | * size_t length ) 309 | * { 310 | * size_t start = 0, next = 0; 311 | * JSONPair_t pair = { 0 }; 312 | * JSONStatus_t result; 313 | * 314 | * result = JSON_Validate( json, length ); 315 | * if( result == JSONSuccess ) 316 | * { 317 | * result = JSON_Iterate( json, length, &start, &next, &pair ); 318 | * } 319 | * 320 | * while( result == JSONSuccess ) 321 | * { 322 | * if( pair.key != NULL ) 323 | * { 324 | * printf( "key: %.*s\t", ( int ) pair.keyLength, pair.key ); 325 | * } 326 | * 327 | * printf( "value: (%s) %.*s\n", json_types[ pair.jsonType ], 328 | * ( int ) pair.valueLength, pair.value ); 329 | * 330 | * result = JSON_Iterate( json, length, &start, &next, &pair ); 331 | * } 332 | * } 333 | * @endcode 334 | */ 335 | /* @[declare_json_iterate] */ 336 | JSONStatus_t JSON_Iterate( const char * buf, 337 | size_t max, 338 | size_t * start, 339 | size_t * next, 340 | JSONPair_t * outPair ); 341 | /* @[declare_json_iterate] */ 342 | 343 | /* *INDENT-OFF* */ 344 | #ifdef __cplusplus 345 | } 346 | #endif 347 | /* *INDENT-ON* */ 348 | 349 | #endif /* ifndef CORE_JSON_H_ */ 350 | -------------------------------------------------------------------------------- /source/include/stdbool.readme: -------------------------------------------------------------------------------- 1 | #ifndef _STDBOOL_H 2 | #define _STDBOOL_H 3 | 4 | /******************************************************************************* 5 | * This file contains the definitions specified in stdbool.h. It is provided to 6 | * allow the library to be built using compilers that do not provide their own 7 | * stdbool.h defintion. 8 | * 9 | * To use this file: 10 | * 11 | * 1) Copy this file into a directory that is in your compiler's include path. 12 | * The directory must be part of the include path for system header files, 13 | * for example passed using gcc's "-I" or "-isystem" options. 14 | * 15 | * 2) Rename the copied file stdbool.h. 16 | * 17 | */ 18 | 19 | #ifndef __cplusplus 20 | 21 | /* _Bool was introduced in C99. */ 22 | #define bool int 23 | #define false 0 24 | #define true 1 25 | 26 | #endif 27 | 28 | #define __bool_true_false_are_defined 1 29 | 30 | #endif /* _STDBOOL_H */ 31 | -------------------------------------------------------------------------------- /source/include/stdint.readme: -------------------------------------------------------------------------------- 1 | #ifndef _STDINT_H 2 | #define _STDINT_H 3 | 4 | /******************************************************************************* 5 | * THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions 6 | * necessary to build the library code. It is provided to allow the library to 7 | * be built using compilers that do not provide their own stdint.h definition. 8 | * 9 | * To use this file: 10 | * 11 | * 1) Copy this file into a directory that is in your compiler's include path. 12 | * The directory must be part of the include path for system header file, 13 | * for example passed using gcc's "-I" or "-isystem" options. 14 | * 15 | * 2) Rename the copied file stdint.h. 16 | * 17 | */ 18 | 19 | typedef signed char int8_t; 20 | typedef unsigned char uint8_t; 21 | typedef short int16_t; 22 | typedef unsigned short uint16_t; 23 | typedef long int32_t; 24 | typedef unsigned long uint32_t; 25 | typedef long long int64_t; 26 | typedef unsigned long long uint64_t; 27 | 28 | #define INT8_MAX ( ( signed char ) 127 ) 29 | #define UINT8_MAX ( ( unsigned char ) 255 ) 30 | #define INT16_MAX ( ( short ) 32767 ) 31 | #define UINT16_MAX ( ( unsigned short ) 65535 ) 32 | #define INT32_MAX 2147483647L 33 | #define UINT32_MAX 4294967295UL 34 | #define INT64_MAX 9223372036854775807LL 35 | #define UINT64_MAX 18446744073709551615ULL 36 | 37 | #ifndef SIZE_MAX 38 | #define SIZE_MAX ( ( size_t ) -1 ) 39 | #endif 40 | 41 | #endif /* _STDINT_H */ 42 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required( VERSION 3.13.0 ) 2 | project( "CoreJSON unit test" 3 | VERSION 1.0.0 4 | LANGUAGES C ) 5 | 6 | # Allow the project to be organized into folders. 7 | set_property( GLOBAL PROPERTY USE_FOLDERS ON ) 8 | 9 | # Use C90. 10 | set( CMAKE_C_STANDARD 90 ) 11 | set( CMAKE_C_STANDARD_REQUIRED ON ) 12 | 13 | # Do not allow in-source build. 14 | if( ${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR} ) 15 | message( FATAL_ERROR "In-source build is not allowed. Please build in a separate directory, such as ${PROJECT_SOURCE_DIR}/build." ) 16 | endif() 17 | 18 | # Set global path variables. 19 | get_filename_component(__MODULE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) 20 | set( MODULE_ROOT_DIR ${__MODULE_ROOT_DIR} CACHE INTERNAL "coreJSON source root." ) 21 | set( UNIT_TEST_DIR ${MODULE_ROOT_DIR}/test/unit-test CACHE INTERNAL "coreJSON unit test directory." ) 22 | set( UNITY_DIR ${UNIT_TEST_DIR}/Unity CACHE INTERNAL "Unity library source directory." ) 23 | 24 | # If no configuration is defined, turn everything on. 25 | if( NOT DEFINED COV_ANALYSIS AND NOT DEFINED UNITTEST ) 26 | set( COV_ANALYSIS TRUE ) 27 | set( UNITTEST TRUE ) 28 | endif() 29 | 30 | # Configure options to always show in CMake GUI. 31 | option( BUILD_CLONE_SUBMODULES 32 | "Set this to ON to automatically clone any required Git submodules. When OFF, submodules must be manually cloned." 33 | OFF ) 34 | 35 | # Set output directories. 36 | set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) 37 | set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) 38 | set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) 39 | 40 | # ================================ Coverity Analysis Configuration ================================= 41 | 42 | if( COV_ANALYSIS ) 43 | # Include filepaths for source and include. 44 | include( ${MODULE_ROOT_DIR}/jsonFilePaths.cmake ) 45 | # Target for Coverity analysis that builds the library. 46 | add_library( coverity_analysis 47 | ${JSON_SOURCES} ) 48 | # JSON public include path. 49 | target_include_directories( coverity_analysis PUBLIC ${JSON_INCLUDE_PUBLIC_DIRS} ) 50 | 51 | # When building the coverity analysis target we disable debug 52 | target_compile_options(coverity_analysis PUBLIC -DNDEBUG ) 53 | endif() 54 | 55 | # ==================================== Test Configuration ======================================== 56 | 57 | if( UNITTEST ) 58 | # Include Unity build configuration. 59 | include( unit-test/unity_build.cmake ) 60 | 61 | # Check if the Unity source directory exists, and if not present, clone the submodule 62 | # if BUILD_CLONE_SUBMODULES configuration is enabled. 63 | if( NOT EXISTS ${UNITY_DIR}/src ) 64 | # Attempt to clone Unity. 65 | if( ${BUILD_CLONE_SUBMODULES} ) 66 | clone_unity() 67 | else() 68 | message( FATAL_ERROR "The required submodule Unity does not exist. Either clone it manually, or set BUILD_CLONE_SUBMODULES to 1 to automatically clone it during build." ) 69 | endif() 70 | endif() 71 | 72 | # Add unit test and coverage configuration. 73 | 74 | # Use CTest utility for managing test runs. This has to be added BEFORE 75 | # defining test targets with add_test() 76 | enable_testing() 77 | 78 | # Add build targets for Unity and Unit, required for unit testing. 79 | add_unity_targets() 80 | 81 | # Add function to enable Unity based tests and coverage. 82 | include( ${MODULE_ROOT_DIR}/tools/unity/create_test.cmake ) 83 | 84 | # Include build configuration for unit tests. 85 | add_subdirectory( unit-test ) 86 | 87 | # ==================================== Coverage Analysis configuration ============================ 88 | 89 | # Add a target for running coverage on tests. 90 | add_custom_target( coverage 91 | COMMAND ${CMAKE_COMMAND} -DUNITY_DIR=${UNITY_DIR} 92 | -P ${MODULE_ROOT_DIR}/tools/unity/coverage.cmake 93 | DEPENDS unity core_json_utest 94 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 95 | ) 96 | endif() 97 | -------------------------------------------------------------------------------- /test/cbmc/.gitignore: -------------------------------------------------------------------------------- 1 | # Emitted when running CBMC proofs 2 | proofs/**/logs 3 | proofs/**/gotos 4 | proofs/**/report 5 | proofs/**/html 6 | proofs/**/core_json.c 7 | proofs/output 8 | 9 | # Emitted by CBMC Viewer 10 | TAGS-* 11 | 12 | # Emitted by Arpa 13 | arpa_cmake/ 14 | arpa-validation-logs/ 15 | Makefile.arpa 16 | 17 | # Emitted by litani 18 | .ninja_deps 19 | .ninja_log 20 | .litani_cache_dir 21 | 22 | __pycache__/ 23 | -------------------------------------------------------------------------------- /test/cbmc/include/README.md: -------------------------------------------------------------------------------- 1 | CBMC proof include files 2 | ======================== 3 | 4 | This directory contains include files written for CBMC proof. It is 5 | common to write some code to model aspects of the system under test, 6 | and the header files for this code go here. 7 | -------------------------------------------------------------------------------- /test/cbmc/include/core_json_annex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef CORE_JSON_ANNEX_H_ 26 | #define CORE_JSON_ANNEX_H_ 27 | 28 | #include 29 | 30 | #include "core_json.h" 31 | 32 | /* 33 | * These are declarations for the (normally) static functions from core_json.c. 34 | * Please see core_json.c for documentation. 35 | */ 36 | 37 | void skipSpace( const char * buf, 38 | size_t * start, 39 | size_t max ); 40 | 41 | bool skipUTF8( const char * buf, 42 | size_t * start, 43 | size_t max ); 44 | 45 | bool skipEscape( const char * buf, 46 | size_t * start, 47 | size_t max ); 48 | 49 | bool skipString( const char * buf, 50 | size_t * start, 51 | size_t max ); 52 | 53 | bool skipAnyLiteral( const char * buf, 54 | size_t * start, 55 | size_t max ); 56 | 57 | bool skipDigits( const char * buf, 58 | size_t * start, 59 | size_t max, 60 | int32_t * outValue ); 61 | 62 | bool skipNumber( const char * buf, 63 | size_t * start, 64 | size_t max ); 65 | 66 | bool skipSpaceAndComma( const char * buf, 67 | size_t * start, 68 | size_t max ); 69 | 70 | bool skipAnyScalar( const char * buf, 71 | size_t * start, 72 | size_t max ); 73 | 74 | JSONStatus_t skipCollection( const char * buf, 75 | size_t * start, 76 | size_t max ); 77 | 78 | #endif /* ifndef CORE_JSON_ANNEX_H_ */ 79 | -------------------------------------------------------------------------------- /test/cbmc/include/core_json_contracts.h: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef CORE_JSON_CONTRACTS_H_ 26 | #define CORE_JSON_CONTRACTS_H_ 27 | 28 | #include 29 | 30 | #include "core_json.h" 31 | 32 | #define isBool( x ) ( ( x == true ) || ( x == false ) ) 33 | 34 | /* Parameter check fail values for JSON API functions. */ 35 | #define isParameterEnum( x ) ( ( x == JSONNullParameter ) || ( x == JSONBadParameter ) ) 36 | 37 | /* These 3 enums represent all the ways skipCollection() can fail. */ 38 | #define isSkipCollectionFailEnum( x ) \ 39 | ( ( x == JSONPartial ) || ( x == JSONIllegalDocument ) || ( x == JSONMaxDepthExceeded ) ) 40 | 41 | /* All possible return values for skipCollection(). */ 42 | #define isSkipCollectionEnum( x ) ( isSkipCollectionFailEnum( x ) || ( x == JSONSuccess ) ) 43 | 44 | /* All possible return values for JSON_Validate(). */ 45 | #define isJSONValidateEnum( x ) ( isSkipCollectionEnum( x ) || isParameterEnum( x ) ) 46 | 47 | /* All possible return values for JSON_Search(). */ 48 | #define isJSONSearchEnum( x ) ( isJSONValidateEnum( x ) || ( x == JSONNotFound ) ) 49 | 50 | /* All possible return values for JSON_Iterate(). */ 51 | #define isJSONIterateEnum( x ) \ 52 | ( isParameterEnum( x ) || ( x == JSONIllegalDocument ) || \ 53 | ( x == JSONNotFound ) || ( x == JSONSuccess ) ) 54 | 55 | /* All possible type values output from JSON_SearchT(). */ 56 | #define isJSONTypesEnum( x ) \ 57 | ( ( x == JSONString ) || \ 58 | ( x == JSONNumber ) || \ 59 | ( x == JSONTrue ) || \ 60 | ( x == JSONFalse ) || \ 61 | ( x == JSONNull ) || \ 62 | ( x == JSONObject ) || \ 63 | ( x == JSONArray ) ) 64 | 65 | #define IMPLIES( a, b ) ( a ? b : true ) 66 | 67 | /** 68 | * Renaming all contract clauses from CBMC for readability. 69 | * For more information about contracts in CBMC, see 70 | * https://diffblue.github.io/cbmc/contracts-user.html. 71 | */ 72 | #define requires __CPROVER_requires 73 | #define ensures __CPROVER_ensures 74 | #define assigns __CPROVER_assigns 75 | 76 | /** 77 | * Renaming all standard predicates from CBMC for readability. 78 | * For more information about contracts in CBMC, see 79 | * https://diffblue.github.io/cbmc/contracts-user.html. 80 | */ 81 | #define allocated __CPROVER_is_fresh 82 | #define old __CPROVER_old 83 | #define result __CPROVER_return_value 84 | #define pointer_in_range __CPROVER_pointer_in_range_dfcc 85 | 86 | /** 87 | * These are declarations for all predicates used in coreJSON function contracts. 88 | */ 89 | 90 | bool isValidBuffer( const char * buf, 91 | size_t max ); 92 | bool isValidBufferWithStartIndex( const char * buf, 93 | size_t max, 94 | size_t * start ); 95 | bool isValidStart( size_t start, 96 | size_t old_start, 97 | size_t max ); 98 | bool JSON_SearchConstPreconditions( const char * buf, 99 | size_t max, 100 | const char * query, 101 | size_t queryLength, 102 | const char ** outValue, 103 | size_t * outValueLength, 104 | JSONTypes_t * outType ); 105 | bool JSON_SearchConstPostconditions( JSONStatus_t result, 106 | const char * buf, 107 | const char ** outValue, 108 | size_t * outValueLength, 109 | size_t max ); 110 | bool JSON_IteratePreconditions( const char * buf, 111 | size_t max, 112 | size_t * start, 113 | size_t * next, 114 | JSONPair_t * outPair ); 115 | bool JSON_IteratePostconditions( JSONStatus_t result, 116 | const char * buf, 117 | size_t max, 118 | JSONPair_t * outPair ); 119 | JSONStatus_t JSON_ValidatePreconditions( const char * buf, 120 | size_t max ); 121 | bool arraySearchPreconditions( const char * buf, 122 | size_t max, 123 | size_t * outValue, 124 | size_t * outValueLength ); 125 | bool arraySearchPostconditions( bool result, 126 | const char * buf, 127 | size_t max, 128 | size_t * outValue, 129 | size_t * outValueLength, 130 | size_t old_outValue, 131 | size_t old_outValueLength ); 132 | bool objectSearchPreconditions( const char * buf, 133 | size_t max, 134 | const char * query, 135 | size_t queryLength, 136 | size_t * outValue, 137 | size_t * outValueLength ); 138 | bool multiSearchPreconditions( const char * buf, 139 | size_t max, 140 | const char * query, 141 | size_t queryLength, 142 | size_t * outValue, 143 | size_t * outValueLength ); 144 | bool multiSearchPostconditions( JSONStatus_t result, 145 | const char * buf, 146 | size_t max, 147 | size_t * outValue, 148 | size_t * outValueLength, 149 | size_t old_outValue, 150 | size_t old_outValueLength ); 151 | bool skipPostconditions( bool result, 152 | const char * buf, 153 | size_t * start, 154 | size_t old_start, 155 | size_t max, 156 | size_t gap ); 157 | bool skipCollectionPostconditions( JSONStatus_t result, 158 | const char * buf, 159 | size_t * start, 160 | size_t old_start, 161 | size_t max ); 162 | bool skipScalarsPreconditions( const char * buf, 163 | size_t * start, 164 | size_t max, 165 | char mode ); 166 | bool skipAnyScalarPostconditions( bool result, 167 | const char * buf, 168 | size_t * start, 169 | size_t old_start, 170 | size_t max ); 171 | bool skipDigitsPreconditions( const char * buf, 172 | size_t * start, 173 | size_t max, 174 | int32_t * outValue ); 175 | bool skipDigitsPostconditions( bool result, 176 | const char * buf, 177 | size_t * start, 178 | size_t old_start, 179 | size_t max, 180 | size_t gap ); 181 | 182 | /** 183 | * These are declarations for the user-facing functions in core_json.h 184 | * with their respective function contracts. 185 | * 186 | * Please see core_json.h for documentation. 187 | */ 188 | 189 | JSONStatus_t JSON_SearchConst( const char * buf, 190 | size_t max, 191 | const char * query, 192 | size_t queryLength, 193 | const char ** outValue, 194 | size_t * outValueLength, 195 | JSONTypes_t * outType ) 196 | requires( JSON_SearchConstPreconditions( buf, max, query, queryLength, outValue, outValueLength, outType ) ) 197 | assigns( *outValue, *outValueLength, *outType ) 198 | ensures( JSON_SearchConstPostconditions( result, buf, outValue, outValueLength, max ) ) 199 | ; 200 | 201 | JSONStatus_t JSON_Iterate( const char * buf, 202 | size_t max, 203 | size_t * start, 204 | size_t * next, 205 | JSONPair_t * outPair ) 206 | requires( JSON_IteratePreconditions( buf, max, start, next, outPair ) ) 207 | assigns( *start, *next, *outPair ) 208 | ensures( JSON_IteratePostconditions( result, buf, max, outPair ) ) 209 | ; 210 | 211 | JSONStatus_t JSON_Validate( const char * buf, 212 | size_t max ) 213 | requires( JSON_ValidatePreconditions( buf, max ) ) 214 | ensures( isJSONValidateEnum( result ) ) 215 | ; 216 | 217 | /** 218 | * These are declarations for the (normally) static functions from core_json.c 219 | * with their respective function contracts. 220 | * 221 | * Please see core_json.c for documentation. 222 | */ 223 | 224 | bool arraySearch( const char * buf, 225 | size_t max, 226 | uint32_t queryIndex, 227 | size_t * outValue, 228 | size_t * outValueLength ) 229 | requires( arraySearchPreconditions( buf, max, outValue, outValueLength ) ) 230 | assigns( *outValue, *outValueLength ) 231 | ensures( arraySearchPostconditions( result, buf, max, outValue, outValueLength, old( *outValue ), old( *outValueLength ) ) ) 232 | ; 233 | 234 | bool objectSearch( const char * buf, 235 | size_t max, 236 | const char * query, 237 | size_t queryLength, 238 | size_t * outValue, 239 | size_t * outValueLength ) 240 | requires( objectSearchPreconditions( buf, max, query, queryLength, outValue, outValueLength ) ) 241 | assigns( *outValue, *outValueLength ) 242 | ensures( arraySearchPostconditions( result, buf, max, outValue, outValueLength, old( *outValue ), old( *outValueLength ) ) ) 243 | ; 244 | 245 | JSONStatus_t multiSearch( const char * buf, 246 | size_t max, 247 | const char * query, 248 | size_t queryLength, 249 | size_t * outValue, 250 | size_t * outValueLength ) 251 | requires( multiSearchPreconditions( buf, max, query, queryLength, outValue, outValueLength ) ) 252 | assigns( *outValue, *outValueLength ) 253 | ensures( multiSearchPostconditions( result, buf, max, outValue, outValueLength, old( *outValue ), old( *outValueLength ) ) ) 254 | ; 255 | 256 | JSONStatus_t skipCollection( const char * buf, 257 | size_t * start, 258 | size_t max ) 259 | requires( isValidBufferWithStartIndex( buf, max, start ) ) 260 | assigns( *start ) 261 | ensures( skipCollectionPostconditions( result, buf, start, old( *start ), max ) ) 262 | ; 263 | 264 | bool skipScalars( const char * buf, 265 | size_t * start, 266 | size_t max, 267 | char mode ) 268 | requires( skipScalarsPreconditions( buf, start, max, mode ) ) 269 | assigns( *start ) 270 | ensures( isValidStart( *start, old( *start ), max ) ) 271 | ; 272 | 273 | bool skipObjectScalars( const char * buf, 274 | size_t * start, 275 | size_t max ) 276 | requires( isValidBufferWithStartIndex( buf, max, start ) ) 277 | assigns( *start ) 278 | ensures( isValidStart( *start, old( *start ), max ) ) 279 | ; 280 | 281 | bool skipAnyScalar( const char * buf, 282 | size_t * start, 283 | size_t max ) 284 | requires( isValidBufferWithStartIndex( buf, max, start ) ) 285 | assigns( *start ) 286 | ensures( skipAnyScalarPostconditions( result, buf, start, old( *start ), max ) ) 287 | ; 288 | 289 | void skipSpace( const char * buf, 290 | size_t * start, 291 | size_t max ) 292 | requires( isValidBufferWithStartIndex( buf, max, start ) ) 293 | assigns( *start ) 294 | ensures( isValidStart( *start, old( *start ), max ) ) 295 | ; 296 | 297 | bool skipString( const char * buf, 298 | size_t * start, 299 | size_t max ) 300 | requires( isValidBufferWithStartIndex( buf, max, start ) ) 301 | assigns( *start ) 302 | ensures( skipPostconditions( result, buf, start, old( *start ), max, 1 ) ) 303 | ; 304 | 305 | bool skipEscape( const char * buf, 306 | size_t * start, 307 | size_t max ) 308 | requires( isValidBufferWithStartIndex( buf, max, start ) ) 309 | assigns( *start ) 310 | ensures( skipPostconditions( result, buf, start, old( *start ), max, 1 ) ) 311 | ; 312 | 313 | bool skipUTF8( const char * buf, 314 | size_t * start, 315 | size_t max ) 316 | requires( isValidBufferWithStartIndex( buf, max, start ) ) 317 | assigns( *start ) 318 | ensures( skipPostconditions( result, buf, start, old( *start ), max, 0 ) ) 319 | ; 320 | 321 | bool skipDigits( const char * buf, 322 | size_t * start, 323 | size_t max, 324 | int32_t * outValue ) 325 | requires( skipDigitsPreconditions( buf, start, max, outValue ) ) 326 | assigns( *start; 327 | outValue != NULL: *outValue ) 328 | ensures( skipDigitsPostconditions( result, buf, start, old( *start ), max, 0 ) ) 329 | ; 330 | 331 | #endif /* ifndef CORE_JSON_CONTRACTS_H_ */ 332 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_Iterate/JSON_Iterate_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file JSON_Iterate_harness.c 27 | * @brief Implements the proof harness for the JSON_Iterate function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t max; 36 | size_t * start; 37 | size_t * next; 38 | JSONPair_t * outPair; 39 | 40 | JSON_Iterate( buf, max, start, next, outPair ); 41 | } 42 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_Iterate/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=JSON_Iterate 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | CBMC_OBJECT_BITS = 12 12 | 13 | USE_FUNCTION_CONTRACTS += skipAnyScalar 14 | USE_FUNCTION_CONTRACTS += skipCollection 15 | USE_FUNCTION_CONTRACTS += skipSpace 16 | USE_FUNCTION_CONTRACTS += skipString 17 | 18 | include ../Makefile-json.common 19 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_Iterate/README.md: -------------------------------------------------------------------------------- 1 | JSON_Iterate proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `JSON_Iterate`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | For this proof, the following functions are replaced with function contracts. 8 | These functions have separate proofs. 9 | * `skipAnyScalar`; 10 | * `skipCollection`; 11 | * `skipSpace`; 12 | * `skipString`. 13 | 14 | To run the proof. 15 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 16 | to your path; 17 | * Run `make`; 18 | * Open `html/index.html` in a web browser. 19 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_Iterate/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_Iterate/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "JSON_Iterate", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_SearchConst/JSON_SearchConst_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file JSON_SearchConst_harness.c 27 | * @brief Implements the proof harness for the JSON_SearchConst function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t max; 36 | char * query; 37 | size_t queryLength; 38 | char ** outValue; 39 | size_t * outValueLength; 40 | JSONTypes_t * outType; 41 | 42 | JSON_SearchConst( buf, max, query, queryLength, outValue, outValueLength, outType ); 43 | } 44 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_SearchConst/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=JSON_SearchConst 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | CBMC_OBJECT_BITS = 11 12 | 13 | USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver kissat 14 | 15 | USE_FUNCTION_CONTRACTS += multiSearch 16 | 17 | include ../Makefile-json.common 18 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_SearchConst/README.md: -------------------------------------------------------------------------------- 1 | JSON_SearchConst proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `JSON_SearchConst`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | For this proof, the following functions are replaced with function contracts. 8 | These functions have separate proofs. 9 | * `skipAnyScalar`; 10 | * `skipCollection`; 11 | * `skipSpace`; 12 | * `skipString`. 13 | 14 | To run the proof. 15 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 16 | to your path; 17 | * Run `make`; 18 | * Open `html/index.html` in a web browser. 19 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_SearchConst/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_SearchConst/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "JSON_SearchConst", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_Validate/JSON_Validate_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file JSON_Validate_harness.c 27 | * @brief Implements the proof harness for the JSON_Validate function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t max; 36 | 37 | JSON_Validate( buf, max ); 38 | } 39 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_Validate/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=JSON_Validate 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver cadical 12 | 13 | USE_FUNCTION_CONTRACTS += skipAnyScalar 14 | USE_FUNCTION_CONTRACTS += skipCollection 15 | 16 | include ../Makefile-json.common 17 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_Validate/README.md: -------------------------------------------------------------------------------- 1 | JSON_Validate proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `JSON_Validate`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | For this proof, the following functions are replaced with function contracts. 8 | These functions have separate proofs. 9 | * `skipAnyScalar`; 10 | * `skipCollection`. 11 | 12 | To run the proof. 13 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 14 | to your path; 15 | * Run `make`; 16 | * Open `html/index.html` in a web browser. 17 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_Validate/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/JSON_Validate/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "JSON_Validate", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | DIRS := skipSpace skipSpaceAndComma skipEscape skipAnyLiteral skipUTF8 3 | DIRS += skipNumber skipString skipCollection JSON_Validate JSON_Search 4 | DIRS += JSON_Iterate 5 | 6 | PROOF_COMMANDS := cbmc goto-cc goto-instrument goto-analyzer cbmc-viewer 7 | SHELL_COMMANDS := mawk sed w3m 8 | 9 | # run all the proofs in ascending dependency order 10 | # and show a summary page for each 11 | all: precheck clean 12 | for d in $(DIRS); do \ 13 | echo -n $$d; \ 14 | time make -C $$d 2>&1 | mawk -W interactive 'NR % 30 == 0 {printf "."}'; echo; \ 15 | w3m -cols 120 -dump $$d/html/index.html | sed 's/^/ /'; \ 16 | done 17 | 18 | clean: 19 | for d in $(DIRS); do make -C $$d cleanclean >/dev/null 2>&1; done 20 | 21 | precheck: 22 | @hash $(PROOF_COMMANDS) $(SHELL_COMMANDS) 23 | 24 | .PHONY: all clean precheck 25 | -------------------------------------------------------------------------------- /test/cbmc/proofs/Makefile-json.common: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | HARNESS_ENTRY=harness 5 | 6 | INCLUDES += -I$(CBMC_ROOT)/include 7 | 8 | PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c 9 | PROOF_SOURCES += $(PROOF_SOURCE)/core_json_contracts.c 10 | 11 | PROJECT_SOURCES += $(PROOFDIR)/core_json.c 12 | 13 | CHECKFLAGS += --pointer-primitive-check 14 | 15 | CBMCFLAGS += --slice-formula 16 | 17 | include ../Makefile.common 18 | 19 | cleanclean: veryclean 20 | -$(RM) $(PROOFDIR)/core_json.c 21 | 22 | # Substitution command to pass to sed for patching core_json.c. The 23 | # characters " and # must be escaped with backslash. 24 | CORE_JSON_SED_EXPR = s/^static // 25 | -------------------------------------------------------------------------------- /test/cbmc/proofs/Makefile-project-defines: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # The first line sets the emacs major mode to Makefile 3 | 4 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | # SPDX-License-Identifier: MIT-0 6 | 7 | ################################################################ 8 | # Use this file to give project-specific definitions of the command 9 | # line arguments to pass to CBMC tools like goto-cc to build the goto 10 | # binaries and cbmc to do the property and coverage checking. 11 | # 12 | # Use this file to override most default definitions of variables in 13 | # Makefile.common. 14 | ################################################################ 15 | 16 | # Flags to pass to goto-cc for compilation (typically those passed to gcc -c) 17 | # COMPILE_FLAGS = 18 | COMPILE_FLAGS += -ansi 19 | 20 | PROJECT_NAME = "FreeRTOS coreJSON" 21 | LITANI ?= litani 22 | 23 | # Flags to pass to goto-cc for linking (typically those passed to gcc) 24 | # LINK_FLAGS = 25 | 26 | # Preprocessor include paths -I... 27 | # Consider adding 28 | # INCLUDES += -I$(CBMC_ROOT)/include 29 | # You will want to decide what order that comes in relative to the other 30 | # include directories in your project. 31 | # 32 | # INCLUDES = 33 | INCLUDES += -I$(SRCDIR)/source/include 34 | 35 | # Preprocessor definitions -D... 36 | # DEFINES = 37 | 38 | # Path to arpa executable 39 | # ARPA = 40 | 41 | # Flags to pass to cmake for building the project 42 | # ARPA_CMAKE_FLAGS = 43 | -------------------------------------------------------------------------------- /test/cbmc/proofs/Makefile-project-targets: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # The first line sets the emacs major mode to Makefile 3 | 4 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | # SPDX-License-Identifier: MIT-0 6 | 7 | ################################################################ 8 | # Use this file to give project-specific targets, including targets 9 | # that may depend on targets defined in Makefile.common. 10 | ################################################################ 11 | 12 | # Each proof requires core_json.c to be patched (using sed) and dumped into the 13 | # proof directory. The exact sed invocation differs for each proof. So each 14 | # proof must set the CORE_JSON_SED_EXPR variable, which this rule uses as the 15 | # argument to sed. 16 | $(PROOFDIR)/core_json.c: $(SRCDIR)/source/core_json.c 17 | $(LITANI) add-job \ 18 | --command \ 19 | "sed -E '$(CORE_JSON_SED_EXPR)' $^" \ 20 | --inputs $^ \ 21 | --outputs $@ \ 22 | --stdout-file $@ \ 23 | --ci-stage build \ 24 | --pipeline-name "$(PROOF_UID)" \ 25 | --description "$(PROOF_UID): patching core_json.c" 26 | -------------------------------------------------------------------------------- /test/cbmc/proofs/Makefile-project-testing: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # The first line sets the emacs major mode to Makefile 3 | 4 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | # SPDX-License-Identifier: MIT-0 6 | 7 | ################################################################ 8 | # Use this file to define project-specific targets and definitions for 9 | # unit testing or continuous integration that may depend on targets 10 | # defined in Makefile.common 11 | ################################################################ 12 | -------------------------------------------------------------------------------- /test/cbmc/proofs/Makefile-template-defines: -------------------------------------------------------------------------------- 1 | SRCDIR ?= $(abspath $(PROOF_ROOT)/../../..) 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/README.md: -------------------------------------------------------------------------------- 1 | CBMC proofs 2 | =========== 3 | 4 | This directory contains the CBMC proofs. Each proof is in its own 5 | directory. 6 | 7 | This directory includes four Makefiles. 8 | 9 | One Makefile describes the basic workflow for building and running proofs: 10 | 11 | * Makefile.common: 12 | * make: builds the goto binary, does the cbmc property checking 13 | and coverage checking, and builds the final report. 14 | * make goto: builds the goto binary 15 | * make result: does cbmc property checking 16 | * make coverage: does cbmc coverage checking 17 | * make report: builds the final report 18 | 19 | Three included Makefiles describe project-specific settings and can override 20 | definitions in Makefile.common: 21 | 22 | * Makefile-project-defines: definitions like compiler flags 23 | required to build the goto binaries, and definitions to override 24 | definitions in Makefile.common. 25 | * Makefile-project-targets: other make targets needed for the project 26 | * Makefile-project-testing: other definitions and targets needed for 27 | unit testing or continuous integration. 28 | -------------------------------------------------------------------------------- /test/cbmc/proofs/arraySearch/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=arraySearch 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | CBMC_OBJECT_BITS = 12 12 | 13 | USE_FUNCTION_CONTRACTS += skipAnyScalar 14 | USE_FUNCTION_CONTRACTS += skipCollection 15 | USE_FUNCTION_CONTRACTS += skipSpace 16 | 17 | include ../Makefile-json.common 18 | -------------------------------------------------------------------------------- /test/cbmc/proofs/arraySearch/README.md: -------------------------------------------------------------------------------- 1 | arraySearch proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `arraySearch`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | For this proof, the following functions are replaced with function contracts. 8 | These functions have separate proofs. 9 | * `skipAnyScalar`; 10 | * `skipCollection`; 11 | * `skipSpace`. 12 | 13 | To run the proof. 14 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 15 | to your path; 16 | * Run `make`; 17 | * Open `html/index.html` in a web browser. 18 | -------------------------------------------------------------------------------- /test/cbmc/proofs/arraySearch/arraySearch_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file arraySearch_harness.c 27 | * @brief Implements the proof harness for the arraySearch function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t max; 36 | uint32_t queryIndex; 37 | char ** outValue; 38 | size_t * outValueLength; 39 | 40 | arraySearch( buf, max, queryIndex, outValue, outValueLength ); 41 | } 42 | -------------------------------------------------------------------------------- /test/cbmc/proofs/arraySearch/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/arraySearch/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "arraySearch", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeRTOS/coreJSON/40244174a1a71be54a7122b941d68f9298f2d67c/test/cbmc/proofs/lib/__init__.py -------------------------------------------------------------------------------- /test/cbmc/proofs/lib/print_tool_versions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # SPDX-License-Identifier: MIT-0 5 | 6 | 7 | import logging 8 | import pathlib 9 | import shutil 10 | import subprocess 11 | 12 | 13 | _TOOLS = [ 14 | "cadical", 15 | "cbmc", 16 | "cbmc-viewer", 17 | "cbmc-starter-kit-update", 18 | "kissat", 19 | "litani", 20 | ] 21 | 22 | 23 | def _format_versions(table): 24 | lines = [ 25 | "", 26 | '', 27 | ] 28 | for tool, version in table.items(): 29 | if version: 30 | v_str = f'
{version}
' 31 | else: 32 | v_str = 'not found' 33 | lines.append( 34 | f'' 36 | f'') 37 | lines.append("
Tool Versions
{tool}:{v_str}
") 38 | return "\n".join(lines) 39 | 40 | 41 | def _get_tool_versions(): 42 | ret = {} 43 | for tool in _TOOLS: 44 | err = f"Could not determine version of {tool}: " 45 | ret[tool] = None 46 | if not shutil.which(tool): 47 | logging.error("%s'%s' not found on $PATH", err, tool) 48 | continue 49 | cmd = [tool, "--version"] 50 | proc = subprocess.Popen(cmd, text=True, stdout=subprocess.PIPE) 51 | try: 52 | out, _ = proc.communicate(timeout=10) 53 | except subprocess.TimeoutExpired: 54 | logging.error("%s'%s --version' timed out", err, tool) 55 | continue 56 | if proc.returncode: 57 | logging.error( 58 | "%s'%s --version' returned %s", err, tool, str(proc.returncode)) 59 | continue 60 | ret[tool] = out.strip() 61 | return ret 62 | 63 | 64 | def main(): 65 | exe_name = pathlib.Path(__file__).name 66 | logging.basicConfig(format=f"{exe_name}: %(message)s") 67 | 68 | table = _get_tool_versions() 69 | out = _format_versions(table) 70 | print(out) 71 | 72 | 73 | if __name__ == "__main__": 74 | main() 75 | -------------------------------------------------------------------------------- /test/cbmc/proofs/lib/summarize.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | import argparse 5 | import json 6 | import logging 7 | import os 8 | import sys 9 | 10 | 11 | DESCRIPTION = """Print 2 tables in GitHub-flavored Markdown that summarize 12 | an execution of CBMC proofs.""" 13 | 14 | 15 | def get_args(): 16 | """Parse arguments for summarize script.""" 17 | parser = argparse.ArgumentParser(description=DESCRIPTION) 18 | for arg in [{ 19 | "flags": ["--run-file"], 20 | "help": "path to the Litani run.json file", 21 | "required": True, 22 | }]: 23 | flags = arg.pop("flags") 24 | parser.add_argument(*flags, **arg) 25 | return parser.parse_args() 26 | 27 | 28 | def _get_max_length_per_column_list(data): 29 | ret = [len(item) + 1 for item in data[0]] 30 | for row in data[1:]: 31 | for idx, item in enumerate(row): 32 | ret[idx] = max(ret[idx], len(item) + 1) 33 | return ret 34 | 35 | 36 | def _get_table_header_separator(max_length_per_column_list): 37 | line_sep = "" 38 | for max_length_of_word_in_col in max_length_per_column_list: 39 | line_sep += "|" + "-" * (max_length_of_word_in_col + 1) 40 | line_sep += "|\n" 41 | return line_sep 42 | 43 | 44 | def _get_entries(max_length_per_column_list, row_data): 45 | entries = [] 46 | for row in row_data: 47 | entry = "" 48 | for idx, word in enumerate(row): 49 | max_length_of_word_in_col = max_length_per_column_list[idx] 50 | space_formatted_word = (max_length_of_word_in_col - len(word)) * " " 51 | entry += "| " + word + space_formatted_word 52 | entry += "|\n" 53 | entries.append(entry) 54 | return entries 55 | 56 | 57 | def _get_rendered_table(data): 58 | table = [] 59 | max_length_per_column_list = _get_max_length_per_column_list(data) 60 | entries = _get_entries(max_length_per_column_list, data) 61 | for idx, entry in enumerate(entries): 62 | if idx == 1: 63 | line_sep = _get_table_header_separator(max_length_per_column_list) 64 | table.append(line_sep) 65 | table.append(entry) 66 | table.append("\n") 67 | return "".join(table) 68 | 69 | 70 | def _get_status_and_proof_summaries(run_dict): 71 | """Parse a dict representing a Litani run and create lists summarizing the 72 | proof results. 73 | 74 | Parameters 75 | ---------- 76 | run_dict 77 | A dictionary representing a Litani run. 78 | 79 | 80 | Returns 81 | ------- 82 | A list of 2 lists. 83 | The first sub-list maps a status to the number of proofs with that status. 84 | The second sub-list maps each proof to its status. 85 | """ 86 | count_statuses = {} 87 | proofs = [["Proof", "Status"]] 88 | for proof_pipeline in run_dict["pipelines"]: 89 | status_pretty_name = proof_pipeline["status"].title().replace("_", " ") 90 | try: 91 | count_statuses[status_pretty_name] += 1 92 | except KeyError: 93 | count_statuses[status_pretty_name] = 1 94 | if proof_pipeline["name"] == "print_tool_versions": 95 | continue 96 | proofs.append([proof_pipeline["name"], status_pretty_name]) 97 | statuses = [["Status", "Count"]] 98 | for status, count in count_statuses.items(): 99 | statuses.append([status, str(count)]) 100 | return [statuses, proofs] 101 | 102 | 103 | def print_proof_results(out_file): 104 | """ 105 | Print 2 strings that summarize the proof results. 106 | When printing, each string will render as a GitHub flavored Markdown table. 107 | """ 108 | output = "## Summary of CBMC proof results\n\n" 109 | with open(out_file, encoding='utf-8') as run_json: 110 | run_dict = json.load(run_json) 111 | status_table, proof_table = _get_status_and_proof_summaries(run_dict) 112 | for summary in (status_table, proof_table): 113 | output += _get_rendered_table(summary) 114 | 115 | print(output) 116 | sys.stdout.flush() 117 | 118 | github_summary_file = os.getenv("GITHUB_STEP_SUMMARY") 119 | if github_summary_file: 120 | with open(github_summary_file, "a") as handle: 121 | print(output, file=handle) 122 | handle.flush() 123 | else: 124 | logging.warning( 125 | "$GITHUB_STEP_SUMMARY not set, not writing summary file") 126 | 127 | msg = ( 128 | "Click the 'Summary' button to view a Markdown table " 129 | "summarizing all proof results") 130 | if run_dict["status"] != "success": 131 | logging.error("Not all proofs passed.") 132 | logging.error(msg) 133 | sys.exit(1) 134 | logging.info(msg) 135 | 136 | 137 | if __name__ == '__main__': 138 | args = get_args() 139 | logging.basicConfig(format="%(levelname)s: %(message)s") 140 | try: 141 | print_proof_results(args.run_file) 142 | except Exception as ex: # pylint: disable=broad-except 143 | logging.critical("Could not print results. Exception: %s", str(ex)) 144 | -------------------------------------------------------------------------------- /test/cbmc/proofs/multiSearch/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=multiSearch 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | CBMC_OBJECT_BITS = 12 12 | 13 | USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver kissat 14 | 15 | USE_FUNCTION_CONTRACTS += arraySearch 16 | USE_FUNCTION_CONTRACTS += objectSearch 17 | USE_FUNCTION_CONTRACTS += skipDigits 18 | 19 | include ../Makefile-json.common 20 | -------------------------------------------------------------------------------- /test/cbmc/proofs/multiSearch/README.md: -------------------------------------------------------------------------------- 1 | multiSearch proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `multiSearch`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | For this proof, the following functions are replaced with function contracts. 8 | These functions have separate proofs. 9 | * `arraySearch`; 10 | * `objectSearch`; 11 | * `skipDigits`. 12 | 13 | To run the proof. 14 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 15 | to your path; 16 | * Run `make`; 17 | * Open `html/index.html` in a web browser. 18 | -------------------------------------------------------------------------------- /test/cbmc/proofs/multiSearch/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/multiSearch/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "multiSearch", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/multiSearch/multiSearch_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file multiSearch_harness.c 27 | * @brief Implements the proof harness for the multiSearch function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t max; 36 | char * query; 37 | size_t queryLength; 38 | char * outValue; 39 | size_t * outValueLength; 40 | 41 | multiSearch( buf, max, query, queryLength, outValue, outValueLength ); 42 | } 43 | -------------------------------------------------------------------------------- /test/cbmc/proofs/objectSearch/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=objectSearch 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | CBMC_OBJECT_BITS = 11 12 | 13 | USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver cadical 14 | 15 | USE_FUNCTION_CONTRACTS += skipAnyScalar 16 | USE_FUNCTION_CONTRACTS += skipCollection 17 | USE_FUNCTION_CONTRACTS += skipSpace 18 | USE_FUNCTION_CONTRACTS += skipString 19 | 20 | include ../Makefile-json.common 21 | -------------------------------------------------------------------------------- /test/cbmc/proofs/objectSearch/README.md: -------------------------------------------------------------------------------- 1 | objectSearch proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `objectSearch`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | For this proof, the following functions are replaced with function contracts. 8 | These functions have separate proofs. 9 | * `skipAnyScalar`; 10 | * `skipCollection`; 11 | * `skipSpace`; 12 | * `skipString`. 13 | 14 | To run the proof. 15 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 16 | to your path; 17 | * Run `make`; 18 | * Open `html/index.html` in a web browser. 19 | -------------------------------------------------------------------------------- /test/cbmc/proofs/objectSearch/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/objectSearch/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "objectSearch", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/objectSearch/objectSearch_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file objectSearch_harness.c 27 | * @brief Implements the proof harness for the objectSearch function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t max; 36 | char * query; 37 | size_t queryLength; 38 | char ** outValue; 39 | size_t * outValueLength; 40 | 41 | objectSearch( buf, max, query, queryLength, outValue, outValueLength ); 42 | } 43 | -------------------------------------------------------------------------------- /test/cbmc/proofs/run-cbmc-proofs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # SPDX-License-Identifier: MIT-0 5 | 6 | 7 | import argparse 8 | import asyncio 9 | import json 10 | import logging 11 | import math 12 | import os 13 | import pathlib 14 | import re 15 | import subprocess 16 | import sys 17 | import tempfile 18 | import uuid 19 | 20 | from lib.summarize import print_proof_results 21 | 22 | 23 | DESCRIPTION = "Configure and run all CBMC proofs in parallel" 24 | 25 | # Keep the epilog hard-wrapped at 70 characters, as it gets printed 26 | # verbatim in the terminal. 70 characters stops here --------------> | 27 | EPILOG = """ 28 | This tool automates the process of running `make report` in each of 29 | the CBMC proof directories. The tool calculates the dependency graph 30 | of all tasks needed to build, run, and report on all the proofs, and 31 | executes these tasks in parallel. 32 | 33 | The tool is roughly equivalent to doing this: 34 | 35 | litani init --project "my-cool-project"; 36 | 37 | find . -name cbmc-proof.txt | while read -r proof; do 38 | pushd $(dirname ${proof}); 39 | 40 | # The `make _report` rule adds a single proof to litani 41 | # without running it 42 | make _report; 43 | 44 | popd; 45 | done 46 | 47 | litani run-build; 48 | 49 | except that it is much faster and provides some convenience options. 50 | The CBMC CI runs this script with no arguments to build and run all 51 | proofs in parallel. The value of "my-cool-project" is taken from the 52 | PROJECT_NAME variable in Makefile-project-defines. 53 | 54 | The --no-standalone argument omits the `litani init` and `litani 55 | run-build`; use it when you want to add additional proof jobs, not 56 | just the CBMC ones. In that case, you would run `litani init` 57 | yourself; then run `run-cbmc-proofs --no-standalone`; add any 58 | additional jobs that you want to execute with `litani add-job`; and 59 | finally run `litani run-build`. 60 | 61 | The litani dashboard will be written under the `output` directory; the 62 | cbmc-viewer reports remain in the `$PROOF_DIR/report` directory. The 63 | HTML dashboard from the latest Litani run will always be symlinked to 64 | `output/latest/html/index.html`, so you can keep that page open in 65 | your browser and reload the page whenever you re-run this script. 66 | """ 67 | # 70 characters stops here ----------------------------------------> | 68 | 69 | 70 | def get_project_name(): 71 | cmd = [ 72 | "make", 73 | "--no-print-directory", 74 | "-f", "Makefile.common", 75 | "echo-project-name", 76 | ] 77 | logging.debug(" ".join(cmd)) 78 | proc = subprocess.run(cmd, universal_newlines=True, stdout=subprocess.PIPE, check=False) 79 | if proc.returncode: 80 | logging.critical("could not run make to determine project name") 81 | sys.exit(1) 82 | if not proc.stdout.strip(): 83 | logging.warning( 84 | "project name has not been set; using generic name instead. " 85 | "Set the PROJECT_NAME value in Makefile-project-defines to " 86 | "remove this warning") 87 | return "" 88 | return proc.stdout.strip() 89 | 90 | 91 | def get_args(): 92 | pars = argparse.ArgumentParser( 93 | description=DESCRIPTION, epilog=EPILOG, 94 | formatter_class=argparse.RawDescriptionHelpFormatter) 95 | for arg in [{ 96 | "flags": ["-j", "--parallel-jobs"], 97 | "type": int, 98 | "metavar": "N", 99 | "help": "run at most N proof jobs in parallel", 100 | }, { 101 | "flags": ["--fail-on-proof-failure"], 102 | "action": "store_true", 103 | "help": "exit with return code `10' if any proof failed" 104 | " (default: exit 0)", 105 | }, { 106 | "flags": ["--no-standalone"], 107 | "action": "store_true", 108 | "help": "only configure proofs: do not initialize nor run", 109 | }, { 110 | "flags": ["-p", "--proofs"], 111 | "nargs": "+", 112 | "metavar": "DIR", 113 | "help": "only run proof in directory DIR (can pass more than one)", 114 | }, { 115 | "flags": ["--project-name"], 116 | "metavar": "NAME", 117 | "default": get_project_name(), 118 | "help": "project name for report. Default: %(default)s", 119 | }, { 120 | "flags": ["--marker-file"], 121 | "metavar": "FILE", 122 | "default": "cbmc-proof.txt", 123 | "help": ( 124 | "name of file that marks proof directories. Default: " 125 | "%(default)s"), 126 | }, { 127 | "flags": ["--no-memory-profile"], 128 | "action": "store_true", 129 | "help": "disable memory profiling, even if Litani supports it" 130 | }, { 131 | "flags": ["--no-expensive-limit"], 132 | "action": "store_true", 133 | "help": "do not limit parallelism of 'EXPENSIVE' jobs", 134 | }, { 135 | "flags": ["--expensive-jobs-parallelism"], 136 | "metavar": "N", 137 | "default": 1, 138 | "type": int, 139 | "help": ( 140 | "how many proof jobs marked 'EXPENSIVE' to run in parallel. " 141 | "Default: %(default)s"), 142 | }, { 143 | "flags": ["--verbose"], 144 | "action": "store_true", 145 | "help": "verbose output", 146 | }, { 147 | "flags": ["--debug"], 148 | "action": "store_true", 149 | "help": "debug output", 150 | }, { 151 | "flags": ["--summarize"], 152 | "action": "store_true", 153 | "help": "summarize proof results with two tables on stdout", 154 | }, { 155 | "flags": ["--version"], 156 | "action": "version", 157 | "version": "CBMC starter kit 2.10", 158 | "help": "display version and exit" 159 | }, { 160 | "flags": ["--no-coverage"], 161 | "action": "store_true", 162 | "help": "do property checking without coverage checking" 163 | }]: 164 | flags = arg.pop("flags") 165 | pars.add_argument(*flags, **arg) 166 | return pars.parse_args() 167 | 168 | 169 | def set_up_logging(verbose): 170 | if verbose: 171 | level = logging.DEBUG 172 | else: 173 | level = logging.WARNING 174 | logging.basicConfig( 175 | format="run-cbmc-proofs: %(message)s", level=level) 176 | 177 | 178 | def task_pool_size(): 179 | ret = os.cpu_count() 180 | if ret is None or ret < 3: 181 | return 1 182 | return ret - 2 183 | 184 | 185 | def print_counter(counter): 186 | # pylint: disable=consider-using-f-string 187 | print("\rConfiguring CBMC proofs: " 188 | "{complete:{width}} / {total:{width}}".format(**counter), end="", file=sys.stderr) 189 | 190 | 191 | def get_proof_dirs(proof_root, proof_list, marker_file): 192 | if proof_list is not None: 193 | proofs_remaining = list(proof_list) 194 | else: 195 | proofs_remaining = [] 196 | 197 | for root, _, fyles in os.walk(proof_root): 198 | proof_name = str(pathlib.Path(root).name) 199 | if root != str(proof_root) and ".litani_cache_dir" in fyles: 200 | pathlib.Path(f"{root}/.litani_cache_dir").unlink() 201 | if proof_list and proof_name not in proof_list: 202 | continue 203 | if proof_list and proof_name in proofs_remaining: 204 | proofs_remaining.remove(proof_name) 205 | if marker_file in fyles: 206 | yield root 207 | 208 | if proofs_remaining: 209 | logging.critical( 210 | "The following proofs were not found: %s", 211 | ", ".join(proofs_remaining)) 212 | sys.exit(1) 213 | 214 | 215 | def run_build(litani, jobs, fail_on_proof_failure, summarize): 216 | cmd = [str(litani), "run-build"] 217 | if jobs: 218 | cmd.extend(["-j", str(jobs)]) 219 | if fail_on_proof_failure: 220 | cmd.append("--fail-on-pipeline-failure") 221 | if summarize: 222 | out_file = pathlib.Path(tempfile.gettempdir(), "run.json").resolve() 223 | cmd.extend(["--out-file", str(out_file)]) 224 | 225 | logging.debug(" ".join(cmd)) 226 | proc = subprocess.run(cmd, check=False) 227 | 228 | if proc.returncode and not fail_on_proof_failure: 229 | logging.critical("Failed to run litani run-build") 230 | sys.exit(1) 231 | 232 | if summarize: 233 | print_proof_results(out_file) 234 | out_file.unlink() 235 | 236 | if proc.returncode: 237 | logging.error("One or more proofs failed") 238 | sys.exit(10) 239 | 240 | def get_litani_path(proof_root): 241 | cmd = [ 242 | "make", 243 | "--no-print-directory", 244 | f"PROOF_ROOT={proof_root}", 245 | "-f", "Makefile.common", 246 | "litani-path", 247 | ] 248 | logging.debug(" ".join(cmd)) 249 | proc = subprocess.run(cmd, universal_newlines=True, stdout=subprocess.PIPE, check=False) 250 | if proc.returncode: 251 | logging.critical("Could not determine path to litani") 252 | sys.exit(1) 253 | return proc.stdout.strip() 254 | 255 | 256 | def get_litani_capabilities(litani_path): 257 | cmd = [litani_path, "print-capabilities"] 258 | proc = subprocess.run( 259 | cmd, text=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, check=False) 260 | if proc.returncode: 261 | return [] 262 | try: 263 | return json.loads(proc.stdout) 264 | except RuntimeError: 265 | logging.warning("Could not load litani capabilities: '%s'", proc.stdout) 266 | return [] 267 | 268 | 269 | def check_uid_uniqueness(proof_dir, proof_uids): 270 | with (pathlib.Path(proof_dir) / "Makefile").open() as handle: 271 | for line in handle: 272 | match = re.match(r"^PROOF_UID\s*=\s*(?P\w+)", line) 273 | if not match: 274 | continue 275 | if match["uid"] not in proof_uids: 276 | proof_uids[match["uid"]] = proof_dir 277 | return 278 | 279 | logging.critical( 280 | "The Makefile in directory '%s' should have a different " 281 | "PROOF_UID than the Makefile in directory '%s'", 282 | proof_dir, proof_uids[match["uid"]]) 283 | sys.exit(1) 284 | 285 | logging.critical( 286 | "The Makefile in directory '%s' should contain a line like", proof_dir) 287 | logging.critical("PROOF_UID = ...") 288 | logging.critical("with a unique identifier for the proof.") 289 | sys.exit(1) 290 | 291 | 292 | def should_enable_memory_profiling(litani_caps, args): 293 | if args.no_memory_profile: 294 | return False 295 | return "memory_profile" in litani_caps 296 | 297 | 298 | def should_enable_pools(litani_caps, args): 299 | if args.no_expensive_limit: 300 | return False 301 | return "pools" in litani_caps 302 | 303 | 304 | async def configure_proof_dirs( # pylint: disable=too-many-arguments 305 | queue, counter, proof_uids, enable_pools, enable_memory_profiling, report_target, debug): 306 | while True: 307 | print_counter(counter) 308 | path = str(await queue.get()) 309 | 310 | check_uid_uniqueness(path, proof_uids) 311 | 312 | pools = ["ENABLE_POOLS=true"] if enable_pools else [] 313 | profiling = [ 314 | "ENABLE_MEMORY_PROFILING=true"] if enable_memory_profiling else [] 315 | 316 | # Allow interactive tasks to preempt proof configuration 317 | proc = await asyncio.create_subprocess_exec( 318 | "nice", "-n", "15", "make", *pools, 319 | *profiling, "-B", report_target, "" if debug else "--quiet", cwd=path, 320 | stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) 321 | stdout, stderr = await proc.communicate() 322 | logging.debug("returncode: %s", str(proc.returncode)) 323 | logging.debug("stdout:") 324 | for line in stdout.decode().splitlines(): 325 | logging.debug(line) 326 | logging.debug("stderr:") 327 | for line in stderr.decode().splitlines(): 328 | logging.debug(line) 329 | 330 | counter["fail" if proc.returncode else "pass"].append(path) 331 | counter["complete"] += 1 332 | 333 | print_counter(counter) 334 | queue.task_done() 335 | 336 | 337 | def add_tool_version_job(): 338 | cmd = [ 339 | "litani", "add-job", 340 | "--command", "./lib/print_tool_versions.py .", 341 | "--description", "printing out tool versions", 342 | "--phony-outputs", str(uuid.uuid4()), 343 | "--pipeline-name", "print_tool_versions", 344 | "--ci-stage", "report", 345 | "--tags", "front-page-text", 346 | ] 347 | proc = subprocess.run(cmd) 348 | if proc.returncode: 349 | logging.critical("Could not add tool version printing job") 350 | sys.exit(1) 351 | 352 | 353 | async def main(): # pylint: disable=too-many-locals 354 | args = get_args() 355 | set_up_logging(args.verbose) 356 | 357 | proof_root = pathlib.Path(os.getcwd()) 358 | litani = get_litani_path(proof_root) 359 | 360 | litani_caps = get_litani_capabilities(litani) 361 | enable_pools = should_enable_pools(litani_caps, args) 362 | init_pools = [ 363 | "--pools", f"expensive:{args.expensive_jobs_parallelism}" 364 | ] if enable_pools else [] 365 | 366 | if not args.no_standalone: 367 | cmd = [ 368 | str(litani), "init", *init_pools, "--project", args.project_name, 369 | "--no-print-out-dir", 370 | ] 371 | 372 | if "output_directory_flags" in litani_caps: 373 | out_prefix = proof_root / "output" 374 | out_symlink = out_prefix / "latest" 375 | out_index = out_symlink / "html" / "index.html" 376 | cmd.extend([ 377 | "--output-prefix", str(out_prefix), 378 | "--output-symlink", str(out_symlink), 379 | ]) 380 | print( 381 | "\nFor your convenience, the output of this run will be symbolically linked to ", 382 | out_index, "\n") 383 | 384 | logging.debug(" ".join(cmd)) 385 | proc = subprocess.run(cmd, check=False) 386 | if proc.returncode: 387 | logging.critical("Failed to run litani init") 388 | sys.exit(1) 389 | 390 | proof_dirs = list(get_proof_dirs( 391 | proof_root, args.proofs, args.marker_file)) 392 | if not proof_dirs: 393 | logging.critical("No proof directories found") 394 | sys.exit(1) 395 | 396 | proof_queue = asyncio.Queue() 397 | for proof_dir in proof_dirs: 398 | proof_queue.put_nowait(proof_dir) 399 | 400 | counter = { 401 | "pass": [], 402 | "fail": [], 403 | "complete": 0, 404 | "total": len(proof_dirs), 405 | "width": int(math.log10(len(proof_dirs))) + 1 406 | } 407 | 408 | proof_uids = {} 409 | tasks = [] 410 | 411 | enable_memory_profiling = should_enable_memory_profiling(litani_caps, args) 412 | report_target = "_report_no_coverage" if args.no_coverage else "_report" 413 | 414 | for _ in range(task_pool_size()): 415 | task = asyncio.create_task(configure_proof_dirs( 416 | proof_queue, counter, proof_uids, enable_pools, 417 | enable_memory_profiling, report_target, args.debug)) 418 | tasks.append(task) 419 | 420 | await proof_queue.join() 421 | 422 | add_tool_version_job() 423 | 424 | print_counter(counter) 425 | print("", file=sys.stderr) 426 | 427 | if counter["fail"]: 428 | logging.critical( 429 | "Failed to configure the following proofs:\n%s", "\n".join( 430 | [str(f) for f in counter["fail"]])) 431 | sys.exit(1) 432 | 433 | if not args.no_standalone: 434 | run_build(litani, args.parallel_jobs, args.fail_on_proof_failure, args.summarize) 435 | 436 | 437 | if __name__ == "__main__": 438 | asyncio.run(main()) 439 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipAnyScalar/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=skipAnyScalar 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | USE_FUNCTION_CONTRACTS += skipDigits 12 | USE_FUNCTION_CONTRACTS += skipString 13 | 14 | include ../Makefile-json.common 15 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipAnyScalar/README.md: -------------------------------------------------------------------------------- 1 | skipAnyScalar proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `skipAnyScalar`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | For this proof, the following functions are replaced with function contracts. 8 | These functions have separate proofs. 9 | * `skipString`. 10 | 11 | To run the proof. 12 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 13 | to your path; 14 | * Run `make`; 15 | * Open `html/index.html` in a web browser. -------------------------------------------------------------------------------- /test/cbmc/proofs/skipAnyScalar/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipAnyScalar/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "skipAnyLiteral", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipAnyScalar/skipAnyScalar_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file skipAnyLiteral_harness.c 27 | * @brief Implements the proof harness for the skipAnyLiteral function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t * start; 36 | size_t max; 37 | 38 | skipAnyScalar( buf, start, max ); 39 | } 40 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipCollection/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=skipCollection 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | CBMC_OBJECT_BITS = 10 12 | 13 | USE_FUNCTION_CONTRACTS += skipScalars 14 | USE_FUNCTION_CONTRACTS += skipSpace 15 | 16 | include ../Makefile-json.common 17 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipCollection/README.md: -------------------------------------------------------------------------------- 1 | skipCollection proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `skipCollection`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | For this proof, the following functions are replaced with function contracts. 8 | These functions have separate proofs. 9 | * `skipScalars`; 10 | * `skipSpace`. 11 | 12 | To run the proof. 13 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 14 | to your path; 15 | * Run `make`; 16 | * Open `html/index.html` in a web browser. 17 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipCollection/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipCollection/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "skipCollection", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipCollection/skipCollection_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file skipCollection_harness.c 27 | * @brief Implements the proof harness for the skipCollection function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t * start; 36 | size_t max; 37 | 38 | skipCollection( buf, start, max ); 39 | } 40 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipDigits/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=skipDigits 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | include ../Makefile-json.common 12 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipDigits/README.md: -------------------------------------------------------------------------------- 1 | skipDigits proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `skipDigits`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | To run the proof. 8 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 9 | to your path; 10 | * Run `make`; 11 | * Open `html/index.html` in a web browser. 12 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipDigits/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipDigits/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "skipDigits", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipDigits/skipDigits_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file skipDigits_harness.c 27 | * @brief Implements the proof harness for the skipDigits function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t * start; 36 | size_t max; 37 | int32_t * outValue; 38 | 39 | skipDigits( buf, start, max, outValue ); 40 | } 41 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipEscape/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=skipEscape 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | include ../Makefile-json.common 12 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipEscape/README.md: -------------------------------------------------------------------------------- 1 | skipEscape proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `skipEscape`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | To run the proof. 8 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 9 | to your path; 10 | * Run `make`; 11 | * Open `html/index.html` in a web browser. 12 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipEscape/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipEscape/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "skipEscape", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipEscape/skipEscape_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file skipEscape_harness.c 27 | * @brief Implements the proof harness for the skipEscape function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t * start; 36 | size_t max; 37 | 38 | skipEscape( buf, start, max ); 39 | } 40 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipObjectScalars/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=skipObjectScalars 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | CBMC_OBJECT_BITS = 11 12 | 13 | USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver cadical 14 | 15 | USE_FUNCTION_CONTRACTS += skipSpace 16 | USE_FUNCTION_CONTRACTS += skipAnyScalar 17 | USE_FUNCTION_CONTRACTS += skipString 18 | 19 | include ../Makefile-json.common 20 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipObjectScalars/README.md: -------------------------------------------------------------------------------- 1 | skipObjectScalars proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `skipObjectScalars`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | For this proof, the following functions are replaced with function contracts. 8 | These functions have separate proofs. 9 | * `skipAnyScalar`; 10 | * `skipSpace`; 11 | * `skipString`. 12 | 13 | To run the proof. 14 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 15 | to your path; 16 | * Run `make`; 17 | * Open `html/index.html` in a web browser. 18 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipObjectScalars/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipObjectScalars/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "skipObjectScalars", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipObjectScalars/skipObjectScalars_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file skipObjectScalars_harness.c 27 | * @brief Implements the proof harness for the skipObjectScalars function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t * start; 36 | size_t max; 37 | 38 | skipObjectScalars( buf, start, max ); 39 | } 40 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipScalars/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=skipScalars 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | CBMC_OBJECT_BITS = 11 12 | 13 | USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver cadical 14 | 15 | USE_FUNCTION_CONTRACTS += skipAnyScalar 16 | USE_FUNCTION_CONTRACTS += skipObjectScalars 17 | USE_FUNCTION_CONTRACTS += skipSpace 18 | USE_FUNCTION_CONTRACTS += skipString 19 | 20 | include ../Makefile-json.common 21 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipScalars/README.md: -------------------------------------------------------------------------------- 1 | skipScalars proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `skipScalars`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | For this proof, the following functions are replaced with function contracts. 8 | These functions have separate proofs. 9 | * `skipAnyScalar`; 10 | * `skipSpace`; 11 | * `skipString`. 12 | 13 | To run the proof. 14 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 15 | to your path; 16 | * Run `make`; 17 | * Open `html/index.html` in a web browser. 18 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipScalars/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipScalars/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "skipScalars", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipScalars/skipScalars_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file skipAnyLiteral_harness.c 27 | * @brief Implements the proof harness for the skipAnyLiteral function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t * start; 36 | size_t max; 37 | char mode; 38 | 39 | skipScalars( buf, start, max, mode ); 40 | } 41 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipSpace/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=skipSpace 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | include ../Makefile-json.common 12 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipSpace/README.md: -------------------------------------------------------------------------------- 1 | skipSpace proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `skipSpace`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | To run the proof. 8 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 9 | to your path; 10 | * Run `make`; 11 | * Open `html/index.html` in a web browser. 12 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipSpace/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipSpace/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "skipSpace", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipSpace/skipSpace_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file skipSpace_harness.c 27 | * @brief Implements the proof harness for the skipSpace function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t * start; 36 | size_t max; 37 | 38 | skipSpace( buf, start, max ); 39 | } 40 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipString/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=skipString 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | CBMC_OBJECT_BITS = 10 12 | 13 | USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver cadical 14 | 15 | USE_FUNCTION_CONTRACTS += skipEscape 16 | USE_FUNCTION_CONTRACTS += skipUTF8 17 | 18 | include ../Makefile-json.common 19 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipString/README.md: -------------------------------------------------------------------------------- 1 | skipString proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `skipString`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | For this proof, the following functions are replaced with function contracts. 8 | These functions have separate proofs. 9 | * `skipEscape`; 10 | * `skipUTF8`. 11 | 12 | To run the proof. 13 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 14 | to your path; 15 | * Run `make`; 16 | * Open `html/index.html` in a web browser. 17 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipString/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipString/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "skipString", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipString/skipString_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file skipString_harness.c 27 | * @brief Implements the proof harness for the skipString function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t * start; 36 | size_t max; 37 | 38 | skipString( buf, start, max ); 39 | } 40 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipUTF8/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | PROOF_UID=skipUTF8 5 | CHECK_FUNCTION_CONTRACTS = $(PROOF_UID) 6 | HARNESS_FILE= $(PROOF_UID)_harness 7 | 8 | APPLY_LOOP_CONTRACTS = 1 9 | USE_DYNAMIC_FRAMES = 1 10 | 11 | include ../Makefile-json.common 12 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipUTF8/README.md: -------------------------------------------------------------------------------- 1 | skipUTF8 proof 2 | ============== 3 | 4 | This directory contains a memory safety proof for `skipUTF8`. 5 | The proof runs in a few seconds and provides 100% coverage. 6 | 7 | To run the proof. 8 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer` 9 | to your path; 10 | * Run `make`; 11 | * Open `html/index.html` in a web browser. 12 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipUTF8/cbmc-proof.txt: -------------------------------------------------------------------------------- 1 | # This file marks this directory as containing a CBMC proof. 2 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipUTF8/cbmc-viewer.json: -------------------------------------------------------------------------------- 1 | { "expected-missing-functions": 2 | [ 3 | 4 | ], 5 | "proof-name": "skipUTF8", 6 | "proof-root": "test/cbmc/proofs" 7 | } 8 | -------------------------------------------------------------------------------- /test/cbmc/proofs/skipUTF8/skipUTF8_harness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file skipUTF8_harness.c 27 | * @brief Implements the proof harness for the skipUTF8 function. 28 | */ 29 | 30 | #include "core_json_contracts.h" 31 | 32 | void harness() 33 | { 34 | char * buf; 35 | size_t * start; 36 | size_t max; 37 | 38 | skipUTF8( buf, start, max ); 39 | } 40 | -------------------------------------------------------------------------------- /test/cbmc/sources/README.md: -------------------------------------------------------------------------------- 1 | CBMC proof source code 2 | ====================== 3 | 4 | This directory contains source code written for CBMC proofs. It is 5 | common to write some code to model aspects of the system under test, 6 | and this code goes here. 7 | -------------------------------------------------------------------------------- /test/cbmc/sources/core_json_contracts.c: -------------------------------------------------------------------------------- 1 | /* 2 | * coreJSON v3.3.0 3 | * Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef CORE_JSON_CONTRACTS_C_ 26 | #define CORE_JSON_CONTRACTS_C_ 27 | 28 | #include "core_json_contracts.h" 29 | 30 | /** 31 | * When to use `&` vs `&&`: 32 | * Prefer `cond1 & cond2` when `cond2` can be evaluated without errors without knowing that `cond1` holds: e.g. `( 0 < i ) & ( i < j )`. 33 | * 34 | * Use `cond1 && cond2` when `cond1` must be established first to ensure that `cond2` can be evaluated without error: e.g. 35 | * `( allocated( p, size ) & ( 0 < i & i < size ) ) && p[i] > 0`. 36 | */ 37 | 38 | /* Valid allocated buffer up to size max. */ 39 | bool isValidBuffer( const char * buf, 40 | size_t max ) 41 | { 42 | return ( 0U < max ) 43 | & ( allocated( buf, max ) ); 44 | } 45 | 46 | /* Valid allocated buffer up to size max and allocated start index. */ 47 | bool isValidBufferWithStartIndex( const char * buf, 48 | size_t max, 49 | size_t * start ) 50 | { 51 | return isValidBuffer( buf, max ) 52 | & ( allocated( start, sizeof( *start ) ) ); 53 | } 54 | 55 | /* Invariant for index in the buffer. */ 56 | bool isValidStart( size_t start, 57 | size_t old_start, 58 | size_t max ) 59 | { 60 | return ( start >= old_start ) && 61 | ( ( old_start < max ) ? ( start <= max ) : ( start == old_start ) ); 62 | } 63 | 64 | bool JSON_SearchConstPreconditions( const char * buf, 65 | size_t max, 66 | const char * query, 67 | size_t queryLength, 68 | const char ** outValue, 69 | size_t * outValueLength, 70 | JSONTypes_t * outType ) 71 | { 72 | return ( buf == NULL || allocated( buf, max ) ) 73 | & ( query == NULL || allocated( query, queryLength ) ) 74 | & ( outValue == NULL || allocated( outValue, sizeof( *outValue ) ) ) 75 | & ( outValueLength == NULL || allocated( outValueLength, sizeof( *outValueLength ) ) ) 76 | & ( outType == NULL || allocated( outType, sizeof( *outType ) ) ); 77 | } 78 | 79 | bool JSON_SearchConstPostconditions( JSONStatus_t result, 80 | const char * buf, 81 | const char ** outValue, 82 | size_t * outValueLength, 83 | size_t max ) 84 | { 85 | bool validity = isJSONSearchEnum( result ); 86 | 87 | if( validity && ( result == JSONSuccess ) ) 88 | { 89 | char * endOfValue = *outValue + *outValueLength; 90 | char * endOfBuf = buf + max; 91 | validity = pointer_in_range( buf, endOfValue, endOfBuf ); 92 | } 93 | 94 | return validity; 95 | } 96 | 97 | bool JSON_IteratePreconditions( const char * buf, 98 | size_t max, 99 | size_t * start, 100 | size_t * next, 101 | JSONPair_t * outPair ) 102 | { 103 | return ( 0 < max ) 104 | & ( buf == NULL || allocated( buf, max ) ) 105 | & ( start == NULL || allocated( start, sizeof( *start ) ) ) 106 | & ( next == NULL || allocated( next, sizeof( *next ) ) ) 107 | & ( outPair == NULL || allocated( outPair, sizeof( *outPair ) ) ) 108 | & IMPLIES( outPair != NULL, ( ( outPair->keyLength == 0 && outPair->key == NULL ) || allocated( outPair->key, outPair->keyLength ) ) ) 109 | & IMPLIES( outPair != NULL, ( ( outPair->valueLength == 0 && outPair->value == NULL ) || allocated( outPair->value, outPair->valueLength ) ) ); 110 | } 111 | 112 | bool JSON_IteratePostconditions( JSONStatus_t result, 113 | const char * buf, 114 | size_t max, 115 | JSONPair_t * outPair ) 116 | { 117 | bool validity = isJSONIterateEnum( result ); 118 | 119 | if( validity && ( result == JSONSuccess ) ) 120 | { 121 | validity = IMPLIES( ( outPair->key != NULL ), ( ( outPair->key > buf ) && ( ( outPair->key + outPair->keyLength ) < ( buf + max ) ) ) ) 122 | & IMPLIES( ( outPair->key != NULL ), ( ( outPair->key + outPair->keyLength ) < outPair->value ) ) 123 | & ( ( outPair->value > buf ) && ( ( outPair->value + outPair->valueLength ) <= ( buf + max ) ) ) 124 | & ( isJSONTypesEnum( outPair->jsonType ) ); 125 | } 126 | 127 | return validity; 128 | } 129 | 130 | JSONStatus_t JSON_ValidatePreconditions( const char * buf, 131 | size_t max ) 132 | { 133 | return( buf == NULL || allocated( buf, max ) ); 134 | } 135 | 136 | bool arraySearchPreconditions( const char * buf, 137 | size_t max, 138 | size_t * outValue, 139 | size_t * outValueLength ) 140 | { 141 | return ( isValidBuffer( buf, max ) ) 142 | & ( allocated( outValue, sizeof( *outValue ) ) ) 143 | & ( allocated( outValueLength, sizeof( *outValueLength ) ) ) 144 | & ( *outValueLength <= max ); 145 | } 146 | 147 | bool arraySearchPostconditions( bool result, 148 | const char * buf, 149 | size_t max, 150 | size_t * outValue, 151 | size_t * outValueLength, 152 | size_t old_outValue, 153 | size_t old_outValueLength ) 154 | { 155 | bool validity = true; 156 | 157 | if( result ) 158 | { 159 | validity = ( *outValue < max ) && 160 | ( 0 < *outValueLength && *outValueLength <= max - *outValue ) && 161 | IMPLIES( buf[ *outValue ] == '"', ( 2 <= *outValueLength && *outValueLength <= max - *outValue ) ); 162 | } 163 | else 164 | { 165 | validity = ( *outValue == old_outValue ) && 166 | ( *outValueLength == old_outValueLength ); 167 | } 168 | 169 | return validity; 170 | } 171 | 172 | bool objectSearchPreconditions( const char * buf, 173 | size_t max, 174 | const char * query, 175 | size_t queryLength, 176 | size_t * outValue, 177 | size_t * outValueLength ) 178 | { 179 | return arraySearchPreconditions( buf, max, outValue, outValueLength ) 180 | & ( allocated( query, queryLength ) ); 181 | } 182 | 183 | bool multiSearchPreconditions( const char * buf, 184 | size_t max, 185 | const char * query, 186 | size_t queryLength, 187 | size_t * outValue, 188 | size_t * outValueLength ) 189 | { 190 | return ( isValidBuffer( buf, max ) ) 191 | & ( 0U < queryLength ) 192 | & ( allocated( query, queryLength ) ) 193 | & ( allocated( outValue, sizeof( *outValue ) ) ) 194 | & ( allocated( outValueLength, sizeof( *outValueLength ) ) ); 195 | } 196 | 197 | bool multiSearchPostconditions( JSONStatus_t result, 198 | const char * buf, 199 | size_t max, 200 | size_t * outValue, 201 | size_t * outValueLength, 202 | size_t old_outValue, 203 | size_t old_outValueLength ) 204 | { 205 | bool validity = isJSONSearchEnum( result ) && 206 | arraySearchPostconditions( result == JSONSuccess, buf, max, outValue, outValueLength, old_outValue, old_outValueLength ); 207 | 208 | return validity; 209 | } 210 | 211 | bool skipPostconditions( bool result, 212 | const char * buf, 213 | size_t * start, 214 | size_t old_start, 215 | size_t max, 216 | size_t gap ) 217 | { 218 | bool validity = isValidStart( *start, old_start, max ) && 219 | IMPLIES( result, ( old_start < max ) && ( *start > old_start + gap ) ); 220 | 221 | return validity; 222 | } 223 | 224 | bool skipCollectionPostconditions( JSONStatus_t result, 225 | const char * buf, 226 | size_t * start, 227 | size_t old_start, 228 | size_t max ) 229 | { 230 | bool validity = isSkipCollectionEnum( result ) && 231 | skipPostconditions( ( result == JSONSuccess ), buf, start, old_start, max, 1 ); 232 | 233 | return validity; 234 | } 235 | 236 | bool skipScalarsPreconditions( const char * buf, 237 | size_t * start, 238 | size_t max, 239 | char mode ) 240 | { 241 | return ( ( mode == '{' ) || ( mode == '[' ) ) 242 | & isValidBufferWithStartIndex( buf, max, start ); 243 | } 244 | 245 | bool skipAnyScalarPostconditions( bool result, 246 | const char * buf, 247 | size_t * start, 248 | size_t old_start, 249 | size_t max ) 250 | { 251 | bool validity = skipPostconditions( result, buf, start, old_start, max, 0 ) && 252 | IMPLIES( ( result && ( buf[ old_start ] == '"' ) ), *start >= old_start + 2 ); 253 | 254 | return validity; 255 | } 256 | 257 | bool skipDigitsPreconditions( const char * buf, 258 | size_t * start, 259 | size_t max, 260 | int32_t * outValue ) 261 | { 262 | return ( outValue == NULL || allocated( outValue, sizeof( *outValue ) ) ) 263 | & isValidBufferWithStartIndex( buf, max, start ); 264 | } 265 | 266 | bool skipDigitsPostconditions( bool result, 267 | const char * buf, 268 | size_t * start, 269 | size_t old_start, 270 | size_t max, 271 | size_t gap ) 272 | { 273 | bool validity = skipPostconditions( result, buf, start, old_start, max, 0 ) && 274 | IMPLIES( result, ( ( ( buf[ old_start ] ) >= '0' ) && ( ( buf[ old_start ] ) <= '9' ) ) ); 275 | 276 | return validity; 277 | } 278 | 279 | #endif /* ifndef CORE_JSON_CONTRACTS_C_ */ 280 | -------------------------------------------------------------------------------- /test/unit-test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include( ${MODULE_ROOT_DIR}/jsonFilePaths.cmake ) 2 | 3 | # ==================== Define your project name (edit) ======================== 4 | set(project_name "core_json") 5 | 6 | # ===================== Create your mock here (edit) ======================== 7 | # ================= Create the library under test here (edit) ================== 8 | 9 | # Base name for temporary files 10 | set( TEMP_BASE ${CMAKE_BINARY_DIR}/${project_name} ) 11 | 12 | # Strip static constraints so unit tests may call internal functions 13 | execute_process( COMMAND sed "s/^static //" 14 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 15 | INPUT_FILE ${JSON_SOURCES} 16 | OUTPUT_FILE ${TEMP_BASE}.c 17 | ) 18 | 19 | # Generate a header file for internal functions 20 | execute_process( COMMAND sed -n "/^static.*(/,/^{\$/{s/^static //; s/)\$/&;/; /{/d; p;}" 21 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 22 | INPUT_FILE ${JSON_SOURCES} 23 | OUTPUT_FILE ${TEMP_BASE}_annex.h 24 | ) 25 | 26 | # list the files you would like to test here 27 | list(APPEND real_source_files 28 | ${TEMP_BASE}.c 29 | ) 30 | # list the directories the module under test includes 31 | list(APPEND real_include_directories 32 | ${JSON_INCLUDE_PUBLIC_DIRS} 33 | ) 34 | 35 | # ===================== Create UnitTest Code here (edit) ===================== 36 | 37 | # list the directories your test needs to include 38 | list(APPEND test_include_directories 39 | ${JSON_INCLUDE_PUBLIC_DIRS} 40 | ${UNIT_TEST_DIR} 41 | ${CMAKE_BINARY_DIR} 42 | ) 43 | 44 | # ============================= (end edit) =================================== 45 | 46 | set(real_name "${project_name}_real") 47 | 48 | create_real_library(${real_name} 49 | "${real_source_files}" 50 | "${real_include_directories}" 51 | ) 52 | 53 | list(APPEND utest_link_list 54 | lib${real_name}.a 55 | ) 56 | 57 | list(APPEND utest_dep_list 58 | ${real_name} 59 | ) 60 | 61 | set(utest_name "${project_name}_utest") 62 | set(utest_source "${project_name}_utest.c") 63 | create_test(${utest_name} 64 | ${utest_source} 65 | "${utest_link_list}" 66 | "${utest_dep_list}" 67 | "${test_include_directories}" 68 | ) 69 | -------------------------------------------------------------------------------- /test/unit-test/catch_assert.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | * this software and associated documentation files (the "Software"), to deal in 8 | * the Software without restriction, including without limitation the rights to 9 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | * the Software, and to permit persons to whom the Software is furnished to do so, 11 | * subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | /* 25 | * How to catch an assert: 26 | * - save a jump buffer where execution will resume after the assert 27 | * - setup a handler for the abort signal, call longjmp within 28 | * - optional - close stderr ( fd 2 ) to discard the assert message 29 | * 30 | * Unity also does a longjmp within its TEST_ASSERT* macros, 31 | * so the macro below restores stderr and the prior abort handler 32 | * before calling the Unity macro. 33 | */ 34 | 35 | #ifndef CATCH_ASSERT_H_ 36 | #define CATCH_ASSERT_H_ 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | #ifndef CATCH_JMPBUF 43 | #define CATCH_JMPBUF waypoint_ 44 | #endif 45 | 46 | static jmp_buf CATCH_JMPBUF; 47 | 48 | #pragma GCC diagnostic push 49 | #pragma GCC diagnostic ignored "-Wunused-function" 50 | static void catchHandler_( int signal ) 51 | { 52 | longjmp( CATCH_JMPBUF, signal ); 53 | } 54 | #pragma GCC diagnostic pop 55 | 56 | #define catch_assert( x ) \ 57 | do { \ 58 | int try = 0, catch = 0; \ 59 | int saveFd = dup( 2 ); \ 60 | struct sigaction sa = { 0 }, saveSa; \ 61 | sa.sa_handler = catchHandler_; \ 62 | sigaction( SIGABRT, &sa, &saveSa ); \ 63 | close( 2 ); \ 64 | if( setjmp( CATCH_JMPBUF ) == 0 ) \ 65 | { \ 66 | try++; \ 67 | x; \ 68 | } \ 69 | else \ 70 | { \ 71 | catch++; \ 72 | } \ 73 | sigaction( SIGABRT, &saveSa, NULL ); \ 74 | dup2( saveFd, 2 ); \ 75 | close( saveFd ); \ 76 | TEST_ASSERT_EQUAL( try, catch ); \ 77 | } while( 0 ) 78 | 79 | #endif /* ifndef CATCH_ASSERT_H_ */ 80 | -------------------------------------------------------------------------------- /test/unit-test/unity_build.cmake: -------------------------------------------------------------------------------- 1 | # Macro utility to clone the Unity submodule. 2 | macro( clone_unity ) 3 | find_package( Git REQUIRED ) 4 | message( "Cloning submodule Unity." ) 5 | execute_process( COMMAND rm -rf ${UNITY_DIR} 6 | COMMAND ${GIT_EXECUTABLE} submodule update --checkout --init --recursive ${UNITY_DIR} 7 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 8 | RESULT_VARIABLE UNITY_CLONE_RESULT ) 9 | 10 | if( NOT ${UNITY_CLONE_RESULT} STREQUAL "0" ) 11 | message( FATAL_ERROR "Failed to clone Unity submodule." ) 12 | endif() 13 | endmacro() 14 | 15 | # Macro utility to add library targets for Unity and Unity to build configuration. 16 | macro( add_unity_targets ) 17 | # Build Configuration for Unity and Unity libraries. 18 | list( APPEND UNITY_INCLUDE_DIRS 19 | "${UNITY_DIR}/src/" 20 | "${UNITY_DIR}/extras/fixture/src" 21 | "${UNITY_DIR}/extras/memory/src" 22 | ) 23 | 24 | add_library( unity STATIC 25 | "${UNITY_DIR}/src/unity.c" 26 | "${UNITY_DIR}/extras/fixture/src/unity_fixture.c" 27 | "${UNITY_DIR}/extras/memory/src/unity_memory.c" 28 | ) 29 | 30 | set_target_properties( unity PROPERTIES 31 | ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib 32 | POSITION_INDEPENDENT_CODE ON 33 | ) 34 | 35 | target_include_directories( unity PUBLIC 36 | ${UNITY_INCLUDE_DIRS} 37 | ) 38 | endmacro() 39 | -------------------------------------------------------------------------------- /tools/coverity/README.md: -------------------------------------------------------------------------------- 1 | # Static code analysis for coreJSON library 2 | This directory is made for the purpose of statically testing the MISRA C:2012 compliance of coreJSON using 3 | [Synopsys Coverity](https://www.synopsys.com/software-integrity/security-testing/static-analysis-sast.html) static analysis tool. 4 | To that end, this directory provides a [configuration file](https://github.com/FreeRTOS/coreJSON/blob/main/tools/coverity/misra.config) to use when 5 | building a binary for the tool to analyze. 6 | 7 | > **Note** 8 | For generating the report as outlined below, we have used Coverity version 2018.09. 9 | 10 | For details regarding the suppressed violations in the report (which can be generated using the instructions described below), please 11 | see the [MISRA.md](https://github.com/FreeRTOS/coreJSON/blob/main/MISRA.md) file. 12 | 13 | ## Getting Started 14 | ### Prerequisites 15 | You can run this on a platform supported by Coverity. The list and other details can be found [here](https://documentation.blackduck.com/bundle/coverity-docs/page/deploy-install-guide/topics/supported_platforms_for_coverity_analysis.html). 16 | To compile and run the Coverity target successfully, you must have the following: 17 | 18 | 1. CMake version > 3.13.0 (You can check whether you have this by typing `cmake --version`) 19 | 2. GCC compiler 20 | - You can see the downloading and installation instructions [here](https://gcc.gnu.org/install/). 21 | 3. Download the repo and include the submodules using the following commands. 22 | - `git clone --recurse-submodules git@github.com:FreeRTOS/coreJSON.git ./coreJSON` 23 | - `cd ./coreJSON` 24 | - `git submodule update --checkout --init --recursive` 25 | 26 | ### To build and run coverity: 27 | Go to the root directory of the library and run the following commands in terminal: 28 | 1. Update the compiler configuration in Coverity 29 | ~~~ 30 | cov-configure --force --compiler cc --comptype gcc 31 | ~~~ 32 | 2. Create the build files using CMake in a `build` directory 33 | ~~~ 34 | cmake -B build -S test 35 | ~~~ 36 | 3. Go to the build directory and copy the coverity configuration file 37 | ~~~ 38 | cd build/ 39 | ~~~ 40 | 4. Build the static analysis target 41 | ~~~ 42 | cov-build --emit-complementary-info --dir cov-out make coverity_analysis 43 | ~~~ 44 | 5. Go to the Coverity output directory (`cov-out`) and begin Coverity static analysis 45 | ~~~ 46 | cd cov-out/ 47 | cov-analyze --dir . --coding-standard-config ../../tools/coverity/misra.config --tu-pattern "file('.*/source/.*')" 48 | ~~~ 49 | 6. Format the errors in HTML format so that it is more readable while removing the test and build directory from the report 50 | ~~~ 51 | cov-format-errors --dir . --file "source" --exclude-files '(/build/|/test/)' --html-output html-out; 52 | ~~~ 53 | 7. Format the errors in JSON format to perform a jq query to get a simplified list of any exceptions. 54 | NOTE: A blank output means there are no defects that aren't being suppressed by the config or inline comments. 55 | ~~~ 56 | cov-format-errors --dir . --file "source" --exclude-files '(/build/|/test/)' --json-output-v2 defects.json; 57 | echo -e "\n-------------------------Non-Suppresed Deviations, if any, Listed Below-------------------------\n"; 58 | jq '.issues[] | .events[] | .eventTag ' defects.json | sort | uniq -c | sort -nr; 59 | echo -e "\n-------------------------Non-Suppresed Deviations, if any, Listed Above-------------------------\n"; 60 | ~~~ 61 | 62 | For your convenience the commands above are below to be copy/pasted into a UNIX command friendly terminal. 63 | ~~~ 64 | cov-configure --force --compiler cc --comptype gcc; 65 | cmake -B build -S test; 66 | cd build/; 67 | cov-build --emit-complementary-info --dir cov-out make coverity_analysis; 68 | cd cov-out/ 69 | cov-analyze --dir . --coding-standard-config ../../tools/coverity/misra.config; 70 | cov-format-errors --dir . --file "source" --exclude-files '(/build/|/test/)' --html-output html-out; 71 | cov-format-errors --dir . --file "source" --exclude-files '(/build/|/test/)' --json-output-v2 defects.json; 72 | echo -e "\n-------------------------Non-Suppresed Deviations, if any, Listed Below-------------------------\n"; 73 | jq '.issues[] | .events[] | .eventTag ' defects.json | sort | uniq -c | sort -nr; 74 | echo -e "\n-------------------------Non-Suppresed Deviations, if any, Listed Above-------------------------\n"; 75 | cd ../../; 76 | ~~~ 77 | 78 | You should now have the HTML formatted violations list in a directory named `build/cov-out/html-output`. 79 | With the current configuration and the provided project, you should not see any deviations. -------------------------------------------------------------------------------- /tools/coverity/misra.config: -------------------------------------------------------------------------------- 1 | { 2 | "version" : "2.0", 3 | "standard" : "c2012", 4 | "title": "Coverity MISRA Configuration", 5 | "deviations" : [ 6 | { 7 | "deviation": "Directive 4.9", 8 | "category": "Advisory", 9 | "reason": "Allow inclusion of function like macros." 10 | }, 11 | { 12 | "deviation": "Rule 2.5", 13 | "reason": "Allow unused macros. Library headers may define macros intended for the application's use, but not used by a specific file." 14 | }, 15 | { 16 | "deviation": "Rule 3.1", 17 | "category": "Required", 18 | "reason": "Allow nested comments. Documentation blocks contain comments for example code." 19 | }, 20 | { 21 | "deviation": "Rule 8.7", 22 | "reason": "API functions are not used by library. They must be externally visible in order to be used by the application." 23 | }, 24 | { 25 | "deviation": "Rule 8.13", 26 | "category": "Advisory", 27 | "reason": "Allow one function to have a char * argument without const qualifier." 28 | }, 29 | { 30 | "deviation": "Rule 15.4", 31 | "category": "Advisory", 32 | "reason": "Allow more then one break statement to terminate a loop" 33 | }, 34 | { 35 | "deviation": "Rule 19.2", 36 | "category": "Advisory", 37 | "reason": "Allow a union of a signed and unsigned type of identical sizes." 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /tools/unity/coverage.cmake: -------------------------------------------------------------------------------- 1 | # Taken from amazon-freertos repository 2 | cmake_minimum_required(VERSION 3.13) 3 | set(BINARY_DIR ${CMAKE_BINARY_DIR}) 4 | # reset coverage counters 5 | execute_process( 6 | COMMAND lcov --directory ${CMAKE_BINARY_DIR} 7 | --base-directory ${CMAKE_BINARY_DIR} 8 | --zerocounters 9 | 10 | COMMAND mkdir -p ${CMAKE_BINARY_DIR}/coverage 11 | ) 12 | # make the initial/baseline capture a zeroed out files 13 | execute_process( COMMAND lcov --directory ${CMAKE_BINARY_DIR} 14 | --base-directory ${CMAKE_BINARY_DIR} 15 | --initial 16 | --capture 17 | --rc lcov_branch_coverage=1 18 | --rc genhtml_branch_coverage=1 19 | --output-file=${CMAKE_BINARY_DIR}/base_coverage.info 20 | ) 21 | file(GLOB files "${CMAKE_BINARY_DIR}/bin/tests/*") 22 | 23 | set(REPORT_FILE ${CMAKE_BINARY_DIR}/utest_report.txt) 24 | file(WRITE ${REPORT_FILE} "") 25 | # execute all files in bin directory, gathering the output to show it in CI 26 | foreach(testname ${files}) 27 | get_filename_component(test 28 | ${testname} 29 | NAME_WLE 30 | ) 31 | message("Running ${testname}") 32 | execute_process(COMMAND ${testname} OUTPUT_FILE ${CMAKE_BINARY_DIR}/${test}_out.txt) 33 | 34 | file(READ ${CMAKE_BINARY_DIR}/${test}_out.txt CONTENTS) 35 | file(APPEND ${REPORT_FILE} "${CONTENTS}") 36 | endforeach() 37 | 38 | # generate Junit style xml output 39 | execute_process(COMMAND ruby 40 | ${UNITY_DIR}/auto/parse_output.rb 41 | -xml ${REPORT_FILE} 42 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 43 | ) 44 | 45 | # capture data after running the tests 46 | execute_process( 47 | COMMAND lcov --capture 48 | --rc lcov_branch_coverage=1 49 | --rc genhtml_branch_coverage=1 50 | --base-directory ${CMAKE_BINARY_DIR} 51 | --directory ${CMAKE_BINARY_DIR} 52 | --output-file ${CMAKE_BINARY_DIR}/second_coverage.info 53 | ) 54 | 55 | # combile baseline results (zeros) with the one after running the tests 56 | execute_process( 57 | COMMAND lcov --base-directory ${CMAKE_BINARY_DIR} 58 | --directory ${CMAKE_BINARY_DIR} 59 | --add-tracefile ${CMAKE_BINARY_DIR}/base_coverage.info 60 | --add-tracefile ${CMAKE_BINARY_DIR}/second_coverage.info 61 | --output-file ${CMAKE_BINARY_DIR}/coverage.info 62 | --no-external 63 | --rc lcov_branch_coverage=1 64 | ) 65 | execute_process( 66 | COMMAND genhtml --rc lcov_branch_coverage=1 67 | --branch-coverage 68 | --output-directory ${CMAKE_BINARY_DIR}/coverage 69 | ${CMAKE_BINARY_DIR}/coverage.info 70 | ) 71 | -------------------------------------------------------------------------------- /tools/unity/create_test.cmake: -------------------------------------------------------------------------------- 1 | # Taken from amazon-freertos repository 2 | 3 | #function to create the test executable 4 | function(create_test test_name 5 | test_src 6 | link_list 7 | dep_list 8 | include_list) 9 | include (CTest) 10 | get_filename_component(test_src_absolute ${test_src} ABSOLUTE) 11 | add_custom_command(OUTPUT ${test_name}_runner.c 12 | COMMAND ruby 13 | ${UNITY_DIR}/auto/generate_test_runner.rb 14 | ${MODULE_ROOT_DIR}/tools/unity/project.yml 15 | ${test_src_absolute} 16 | ${test_name}_runner.c 17 | DEPENDS ${test_src} 18 | ) 19 | add_executable(${test_name} ${test_src} ${test_name}_runner.c) 20 | set_target_properties(${test_name} PROPERTIES 21 | COMPILE_FLAG "-O0 -ggdb" 22 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/tests" 23 | INSTALL_RPATH_USE_LINK_PATH TRUE 24 | LINK_FLAGS " \ 25 | -Wl,-rpath,${CMAKE_BINARY_DIR}/lib \ 26 | -Wl,-rpath,${CMAKE_CURRENT_BINARY_DIR}/lib" 27 | ) 28 | target_include_directories(${test_name} PUBLIC 29 | ${include_list} 30 | ) 31 | 32 | target_link_directories(${test_name} PUBLIC 33 | ${CMAKE_CURRENT_BINARY_DIR} 34 | ) 35 | 36 | # link all libraries sent through parameters 37 | foreach(link IN LISTS link_list) 38 | target_link_libraries(${test_name} ${link}) 39 | endforeach() 40 | 41 | # add dependency to all the dep_list parameter 42 | foreach(dependency IN LISTS dep_list) 43 | add_dependencies(${test_name} ${dependency}) 44 | target_link_libraries(${test_name} ${dependency}) 45 | endforeach() 46 | target_link_libraries(${test_name} -lgcov unity) 47 | target_link_directories(${test_name} PUBLIC 48 | ${CMAKE_CURRENT_BINARY_DIR}/lib 49 | ) 50 | add_test(NAME ${test_name} 51 | COMMAND ${CMAKE_BINARY_DIR}/bin/tests/${test_name} 52 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 53 | ) 54 | endfunction() 55 | 56 | function(create_real_library target 57 | src_file 58 | real_include_list) 59 | add_library(${target} STATIC 60 | ${src_file} 61 | ) 62 | target_include_directories(${target} PUBLIC 63 | ${real_include_list} 64 | ) 65 | set_target_properties(${target} PROPERTIES 66 | COMPILE_FLAGS "-Wextra -Wpedantic \ 67 | -fprofile-arcs -ftest-coverage -fprofile-generate \ 68 | -Wno-unused-but-set-variable" 69 | LINK_FLAGS "-fprofile-arcs -ftest-coverage \ 70 | -fprofile-generate " 71 | ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib 72 | ) 73 | endfunction() 74 | -------------------------------------------------------------------------------- /tools/unity/project.yml: -------------------------------------------------------------------------------- 1 | :unity: 2 | :when_no_prototypes: :warn 3 | :enforce_strict_ordering: TRUE 4 | :treat_as: 5 | uint8: HEX8 6 | uint16: HEX16 7 | uint32: UINT32 8 | int8: INT8 9 | bool: UINT8 10 | :treat_externs: :exclude 11 | :weak: __attribute__((weak)) 12 | :treat_externs: :include 13 | --------------------------------------------------------------------------------